matrix.c (6505B)
1 /* Copyright 2012 Jun Wako <wakojun@gmail.com>: TMK Matrix 2 * Copyright 2018 bakageta <amo@bakageta.com> 3 * 4 * This is heavily based on hid_liber/board.{c|h}. 5 * https://github.com/BathroomEpiphanies/AVR-Keyboard 6 * 7 * Copyright (c) 2012 Fredrik Atmer, Bathroom Epiphanies Inc 8 * http://bathroomepiphanies.com 9 * 10 * This program is free software: you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation, either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program. If not, see <http://www.gnu.org/licenses/>. 22 */ 23 24 #include <stdint.h> 25 #include <stdbool.h> 26 #if defined(__AVR__) 27 #include <avr/io.h> 28 #endif 29 #include <util/delay.h> 30 #include "wait.h" 31 #include "print.h" 32 #include "debug.h" 33 #include "util.h" 34 #include "matrix.h" 35 #include "timer.h" 36 37 38 #ifndef DEBOUNCE 39 # define DEBOUNCE 5 40 #endif 41 static uint8_t debouncing = DEBOUNCE; 42 43 // bit array of key state(1:on, 0:off) 44 static matrix_row_t matrix[MATRIX_ROWS]; 45 static matrix_row_t matrix_debouncing[MATRIX_ROWS]; 46 47 48 #define _DDRA (uint8_t *const)&DDRA 49 #define _DDRB (uint8_t *const)&DDRB 50 #define _DDRC (uint8_t *const)&DDRC 51 #define _DDRD (uint8_t *const)&DDRD 52 #define _DDRE (uint8_t *const)&DDRE 53 #define _DDRF (uint8_t *const)&DDRF 54 55 #define _PINA (uint8_t *const)&PINA 56 #define _PINB (uint8_t *const)&PINB 57 #define _PINC (uint8_t *const)&PINC 58 #define _PIND (uint8_t *const)&PIND 59 #define _PINE (uint8_t *const)&PINE 60 #define _PINF (uint8_t *const)&PINF 61 62 #define _PORTA (uint8_t *const)&PORTA 63 #define _PORTB (uint8_t *const)&PORTB 64 #define _PORTC (uint8_t *const)&PORTC 65 #define _PORTD (uint8_t *const)&PORTD 66 #define _PORTE (uint8_t *const)&PORTE 67 #define _PORTF (uint8_t *const)&PORTF 68 69 #define _BIT0 0x01 70 #define _BIT1 0x02 71 #define _BIT2 0x04 72 #define _BIT3 0x08 73 #define _BIT4 0x10 74 #define _BIT5 0x20 75 #define _BIT6 0x40 76 #define _BIT7 0x80 77 78 /* Specifies the ports and pin numbers for the rows */ 79 static 80 uint8_t *const row_ddr[MATRIX_ROWS] = { 81 _DDRB, _DDRB, 82 _DDRC, _DDRC, 83 _DDRD, _DDRD, _DDRD, _DDRD, _DDRD, _DDRD, _DDRD, _DDRD, 84 _DDRF, _DDRF, _DDRF, _DDRF, _DDRF, _DDRF}; 85 86 static 87 uint8_t *const row_port[MATRIX_ROWS] = { 88 _PORTB, _PORTB, 89 _PORTC, _PORTC, 90 _PORTD, _PORTD, _PORTD, _PORTD, _PORTD, _PORTD, _PORTD, _PORTD, 91 _PORTF, _PORTF, _PORTF, _PORTF, _PORTF, _PORTF}; 92 93 static 94 uint8_t *const row_pin[MATRIX_ROWS] = { 95 _PINB, _PINB, 96 _PINC, _PINC, 97 _PIND, _PIND, _PIND, _PIND, _PIND, _PIND, _PIND, _PIND, 98 _PINF, _PINF, _PINF, _PINF, _PINF, _PINF}; 99 100 static 101 const uint8_t row_bit[MATRIX_ROWS] = { 102 _BIT4, _BIT7, 103 _BIT6, _BIT7, 104 _BIT0, _BIT1, _BIT2, _BIT3, _BIT4, _BIT5, _BIT6, _BIT7, 105 _BIT0, _BIT1, _BIT4, _BIT5, _BIT6, _BIT7}; 106 107 static 108 const uint8_t mask = 0x0E; 109 110 /* Specifies the ports and pin numbers for the columns */ 111 static 112 const uint8_t col_bit[MATRIX_COLS] = { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E}; 113 114 __attribute__ ((weak)) 115 void matrix_init_kb(void) { 116 matrix_init_user(); 117 } 118 119 __attribute__ ((weak)) 120 void matrix_scan_kb(void) { 121 matrix_scan_user(); 122 } 123 124 __attribute__ ((weak)) 125 void matrix_init_user(void) { 126 } 127 128 __attribute__ ((weak)) 129 void matrix_scan_user(void) { 130 } 131 132 static 133 inline void pull_column(int col) { 134 PORTB = col_bit[col] | (PORTB & ~mask); 135 } 136 137 static 138 inline void release_column(int col) { 139 } 140 141 /* PORTB is set as input with pull-up resistors 142 PORTC,D,E,F are set to high output */ 143 static 144 void setup_io_pins(void) { 145 uint8_t row; 146 DDRB |= 0x0E; 147 PORTB &= ~0x0E; 148 for(row = 0; row < MATRIX_ROWS; row++) { 149 *row_ddr[row] &= ~row_bit[row]; 150 *row_port[row] &= ~row_bit[row]; 151 } 152 } 153 154 static 155 void setup_leds(void) { 156 DDRB |= 0x60; 157 PORTB |= 0x60; 158 } 159 160 161 inline 162 uint8_t matrix_rows(void) 163 { 164 return MATRIX_ROWS; 165 } 166 167 inline 168 uint8_t matrix_cols(void) 169 { 170 return MATRIX_COLS; 171 } 172 173 void matrix_init(void) 174 { 175 // initialize row and col 176 setup_io_pins(); 177 setup_leds(); 178 179 // initialize matrix state: all keys off 180 for (uint8_t i=0; i < MATRIX_ROWS; i++) { 181 matrix[i] = 0; 182 matrix_debouncing[i] = 0; 183 } 184 185 matrix_init_kb(); 186 } 187 188 uint8_t matrix_scan(void) 189 { 190 for (uint8_t col = 0; col < MATRIX_COLS; col++) { // 0-7 191 pull_column(col); // output hi on theline 192 _delay_us(5); // without this wait it won't read stable value. 193 for (uint8_t row = 0; row < MATRIX_ROWS; row++) { // 0-17 194 bool prev_bit = matrix_debouncing[row] & (1<<col); 195 bool curr_bit = *row_pin[row] & row_bit[row]; 196 if (prev_bit != curr_bit) { 197 matrix_debouncing[row] ^= ((matrix_row_t)1<<col); 198 if (debouncing) { 199 dprintf("bounce!: %02X\n", debouncing); 200 } 201 debouncing = DEBOUNCE; 202 } 203 } 204 release_column(col); 205 } 206 207 if (debouncing) { 208 if (--debouncing) { 209 _delay_ms(1); 210 } else { 211 for (uint8_t i = 0; i < MATRIX_ROWS; i++) { 212 matrix[i] = matrix_debouncing[i]; 213 } 214 } 215 } 216 217 matrix_scan_kb(); 218 return 1; 219 } 220 221 inline 222 bool matrix_has_ghost(void) 223 { 224 return false; 225 } 226 227 inline 228 bool matrix_is_on(uint8_t row, uint8_t col) 229 { 230 return (matrix[row] & ((matrix_row_t)1<<col)); 231 } 232 233 inline 234 matrix_row_t matrix_get_row(uint8_t row) 235 { 236 return matrix[row]; 237 } 238 239 void matrix_print(void) 240 { 241 print("\nr/c 01234567\n"); 242 for (uint8_t row = 0; row < MATRIX_ROWS; row++) { 243 print_hex8(row); print(": "); 244 print_bin_reverse8(matrix_get_row(row)); 245 print("\n"); 246 } 247 }