]> git.friedersdorff.com Git - max/tmk_keyboard.git/blobdiff - macway/matrix.c
add debouncing into macway/matrix.c.
[max/tmk_keyboard.git] / macway / matrix.c
index c2b3fb8b2a08091e84924df528c208af0b89acbf..56fb85896025311ad85cfac7aa485d94a623a239 100644 (file)
@@ -1,3 +1,20 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
 /*
  * scan matrix
  */
 #include <avr/io.h>
 #include <util/delay.h>
 #include "print.h"
+#include "debug.h"
 #include "util.h"
-#include "controller.h"
-#include "matrix_skel.h"
+#include "matrix.h"
+
 
-// matrix is active low. (key on: 0/key off: 1)
-// row: Hi-Z(unselected)/low output(selected)
-//      PD0, PC7, PD7, PF6, PD6, PD1, PD2, PC6, PF7
-// col: input w/pullup
-//      PB0-PB7
+#if (MATRIX_COLS > 16)
+#   error "MATRIX_COLS must not exceed 16"
+#endif
+#if (MATRIX_ROWS > 255)
+#   error "MATRIX_ROWS must not exceed 255"
+#endif
 
-// matrix state buffer
+
+#ifndef DEBOUNCE
+#   define DEBOUNCE    0
+#endif
+static uint8_t debouncing = DEBOUNCE;
+
+// matrix state buffer(1:on, 0:off)
+#if (MATRIX_COLS <= 8)
 static uint8_t *matrix;
 static uint8_t *matrix_prev;
 static uint8_t _matrix0[MATRIX_ROWS];
 static uint8_t _matrix1[MATRIX_ROWS];
+#else
+static uint16_t *matrix;
+static uint16_t *matrix_prev;
+static uint16_t _matrix0[MATRIX_ROWS];
+static uint16_t _matrix1[MATRIX_ROWS];
+#endif
 
+#ifdef MATRIX_HAS_GHOST
 static bool matrix_has_ghost_in_row(uint8_t row);
+#endif
 static uint8_t read_col(void);
 static void unselect_rows(void);
 static void select_row(uint8_t row);
 
 
 inline
-int matrix_rows(void)
+uint8_t matrix_rows(void)
 {
     return MATRIX_ROWS;
 }
 
 inline
-int matrix_cols(void)
+uint8_t matrix_cols(void)
 {
     return MATRIX_COLS;
 }
 
-// this must be called once before matrix_scan.
 void matrix_init(void)
 {
     // initialize row and col
     unselect_rows();
+    // Input with pull-up(DDR:0, PORT:1)
     DDRB = 0x00;
     PORTB = 0xFF;
 
     // initialize matrix state: all keys off
-    for (int i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00;
-    for (int i=0; i < MATRIX_ROWS; i++) _matrix1[i] = 0x00;
+    for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00;
+    for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix1[i] = 0x00;
     matrix = _matrix0;
     matrix_prev = _matrix1;
 }
 
-int matrix_scan(void)
+uint8_t matrix_scan(void)
 {
-    uint8_t *tmp;
-
-    tmp = matrix_prev;
-    matrix_prev = matrix;
-    matrix = tmp;
+    if (!debouncing) {
+        uint8_t *tmp = matrix_prev;
+        matrix_prev = matrix;
+        matrix = tmp;
+    }
 
-    for (int i = 0; i < MATRIX_ROWS; i++) {
+    for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+        unselect_rows();
         select_row(i);
         _delay_us(30);  // without this wait read unstable value.
-        matrix[i] = ~read_col();
-        unselect_rows();
+        if (matrix[i] != (uint8_t)~read_col()) {
+            matrix[i] = (uint8_t)~read_col();
+            if (debouncing) {
+                debug("bounce!: "); debug_hex(debouncing); print("\n");
+            }
+            debouncing = DEBOUNCE;
+        }
+    }
+    unselect_rows();
+
+    if (debouncing) {
+        debouncing--;
     }
+
     return 1;
 }
 
 bool matrix_is_modified(void)
 {
-    for (int i = 0; i < MATRIX_ROWS; i++) {
-        if (matrix[i] != matrix_prev[i])
+    if (debouncing) return false;
+    for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+        if (matrix[i] != matrix_prev[i]) {
             return true;
+        }
     }
     return false;
 }
 
+inline
 bool matrix_has_ghost(void)
 {
-    for (int i = 0; i < MATRIX_ROWS; i++) {
+#ifdef MATRIX_HAS_GHOST
+    for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
         if (matrix_has_ghost_in_row(i))
             return true;
     }
+#endif
     return false;
 }
 
 inline
-bool matrix_is_on(int row, int col)
+bool matrix_is_on(uint8_t row, uint8_t col)
 {
     return (matrix[row] & (1<<col));
 }
 
 inline
-uint16_t matrix_get_row(int row)
+#if (MATRIX_COLS <= 8)
+uint8_t matrix_get_row(uint8_t row)
+#else
+uint16_t matrix_get_row(uint8_t row)
+#endif
 {
     return matrix[row];
 }
@@ -105,25 +160,37 @@ uint16_t matrix_get_row(int row)
 void matrix_print(void)
 {
     print("\nr/c 01234567\n");
-    for (int row = 0; row < matrix_rows(); row++) {
+    for (uint8_t row = 0; row < matrix_rows(); row++) {
         phex(row); print(": ");
+#if (MATRIX_COLS <= 8)
         pbin_reverse(matrix_get_row(row));
+#else
+        pbin_reverse16(matrix_get_row(row));
+#endif
+#ifdef MATRIX_HAS_GHOST
         if (matrix_has_ghost_in_row(row)) {
             print(" <ghost");
         }
+#endif
         print("\n");
     }
 }
 
-int matrix_key_count(void)
+uint8_t matrix_key_count(void)
 {
-    int count = 0;
-    for (int i = 0; i < MATRIX_ROWS; i++) {
+    uint8_t count = 0;
+    for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+#if (MATRIX_COLS <= 8)
         count += bitpop(matrix[i]);
+#else
+        count += bitpop16(matrix[i]);
+#endif
     }
     return count;
 }
 
+#ifdef MATRIX_HAS_GHOST
+inline
 static bool matrix_has_ghost_in_row(uint8_t row)
 {
     // no ghost exists in case less than 2 keys on
@@ -131,102 +198,74 @@ static bool matrix_has_ghost_in_row(uint8_t row)
         return false;
 
     // ghost exists in case same state as other row
-    for (int i=0; i < MATRIX_ROWS; i++) {
+    for (uint8_t i=0; i < MATRIX_ROWS; i++) {
         if (i != row && (matrix[i] & matrix[row]) == matrix[row])
             return true;
     }
     return false;
 }
+#endif
 
+inline
 static uint8_t read_col(void)
 {
     return PINB;
 }
 
+inline
 static void unselect_rows(void)
 {
-    DDRD  = 0x00;
-    PORTD = 0x00;
-    DDRC  = 0x00;
-    PORTC = 0x00;
-    DDRF  = 0x00;
-    PORTF = 0x00;
+    // Hi-Z(DDR:0, PORT:0) to unselect
+    DDRC  &= ~0b11000000; // PC: 7,6
+    PORTC &= ~0b11000000;
+    DDRD  &= ~0b11000111; // PD: 7,6,2,1,0
+    PORTD &= ~0b11000111;
+    DDRF  &= ~0b11000000; // PF: 7,6
+    PORTF &= ~0b11000000;
 }
 
+inline
 static void select_row(uint8_t row)
 {
+    // Output low(DDR:1, PORT:0) to select
+    // row: 0    1    2    3    4    5    6    7    8
+    // pin: PD0, PC7, PD7, PF6, PD6, PD1, PD2, PC6, PF7
     switch (row) {
         case 0:
-            DDRD  = (1<<0);
-            PORTD = 0x00;
-            DDRC  = 0x00;
-            PORTC = 0x00;
-            DDRF  = 0x00;
-            PORTF = 0x00;
+            DDRD  |= (1<<0);
+            PORTD &= ~(1<<0);
             break;
         case 1:
-            DDRD  = 0x00;
-            PORTD = 0x00;
-            DDRC  = (1<<7);
-            PORTC = 0x00;
-            DDRF  = 0x00;
-            PORTF = 0x00;
+            DDRC  |= (1<<7);
+            PORTC &= ~(1<<7);
             break;
         case 2:
-            DDRD  = (1<<7);
-            PORTD = 0x00;
-            DDRC  = 0x00;
-            PORTC = 0x00;
-            DDRF  = 0x00;
-            PORTF = 0x00;
+            DDRD  |= (1<<7);
+            PORTD &= ~(1<<7);
             break;
         case 3:
-            DDRD  = 0x00;
-            PORTD = 0x00;
-            DDRC  = 0x00;
-            PORTC = 0x00;
-            DDRF  = (1<<6);
-            PORTF = 0x00;
+            DDRF  |= (1<<6);
+            PORTF &= ~(1<<6);
             break;
         case 4:
-            DDRD  = (1<<6);
-            PORTD = 0x00;
-            DDRC  = 0x00;
-            PORTC = 0x00;
-            DDRF  = 0x00;
-            PORTF = 0x00;
+            DDRD  |= (1<<6);
+            PORTD &= ~(1<<6);
             break;
         case 5:
-            DDRD  = (1<<1);
-            PORTD = 0x00;
-            DDRC  = 0x00;
-            PORTC = 0x00;
-            DDRF  = 0x00;
-            PORTF = 0x00;
+            DDRD  |= (1<<1);
+            PORTD &= ~(1<<1);
             break;
         case 6:
-            DDRD  = (1<<2);
-            PORTD = 0x00;
-            DDRC  = 0x00;
-            PORTC = 0x00;
-            DDRF  = 0x00;
-            PORTF = 0x00;
+            DDRD  |= (1<<2);
+            PORTD &= ~(1<<2);
             break;
         case 7:
-            DDRD  = 0x00;
-            PORTD = 0x00;
-            DDRC  = (1<<6);
-            PORTC = 0x00;
-            DDRF  = 0x00;
-            PORTF = 0x00;
+            DDRC  |= (1<<6);
+            PORTC &= ~(1<<6);
             break;
         case 8:
-            DDRD  = 0x00;
-            PORTD = 0x00;
-            DDRC  = 0x00;
-            PORTC = 0x00;
-            DDRF  = (1<<7);
-            PORTF = 0x00;
+            DDRF  |= (1<<7);
+            PORTF &= ~(1<<7);
             break;
     }
 }