]> git.donarmstrong.com Git - qmk_firmware.git/blob - keyboards/converter/ibm_5291/matrix.c
58f6e37b650853ae09e90ae55634302935499a4d
[qmk_firmware.git] / keyboards / converter / ibm_5291 / matrix.c
1 /*
2 Copyright 2018 listofoptions <listofoptions@gmail.com>
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 <string.h>
21 #if defined(__AVR__)
22 #include <avr/io.h>
23 #endif
24 #include <util/delay.h>
25
26 #include "wait.h"
27 #include "print.h"
28 #include "debug.h"
29 #include "util.h"
30 #include "matrix.h"
31 #include "timer.h"
32
33 #include "config.h"
34
35
36 #ifndef DEBOUNCING_DELAY
37 #   define DEBOUNCING_DELAY 5
38 #endif
39
40 #define print_matrix_header()      print("\nr/c 01234567\n")
41 #define print_matrix_row(row)      print_bin_reverse8(matrix_get_row(row))
42 #define matrix_bitpop(i)           bitpop(matrix[i])
43 #define ROW_SHIFTER                ((uint8_t)1)
44 #define check_bit(var,pos)         ((var) & (1<<(pos)))
45
46 #define NUM_ROW_PINS 5
47 #define NUM_COL_PINS 2
48
49 static const uint8_t row_pins [NUM_ROW_PINS] = MATRIX_ROW_PINS ;
50 static const uint8_t col_pins [NUM_ROW_PINS] = MATRIX_COL_PINS ;
51
52 #if ( DEBOUNCING_DELAY > 0 )
53 static uint16_t debouncing_time         ;
54 static bool     debouncing      = false ;
55 #endif
56
57 static uint8_t matrix          [MATRIX_ROWS] = {0};
58
59 #if ( DEBOUNCING_DELAY > 0 )
60 static uint8_t matrix_debounce [MATRIX_ROWS] = {0};
61 #endif 
62
63 static
64 inline
65 void toggle_led(void) {
66     uint8_t pin = LED_PIN ;
67     _SFR_IO8((pin >> 4) + 2) ^= _BV(pin & 0xF);
68 }
69
70 static
71 inline
72 void init_led(void) {
73     uint8_t pin = LED_PIN ;
74     _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF);  // OUT
75     _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
76 }
77
78 static
79 inline
80 void init_data(void) {
81     uint8_t pin = MATRIX_DATA_PIN ;
82     _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
83     _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // LO
84 }
85
86 static
87 inline
88 void init_strobe(void) {
89     uint8_t pin = MATRIX_STROBE_PIN ;
90     _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF);  // OUT
91     _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF);  // HI
92 }
93
94 static
95 inline
96 void init_rows(void) {
97     for ( uint8_t i = 0 ; i < NUM_ROW_PINS; ++i ) {
98         uint8_t pin = row_pins[i];
99         _SFR_IO8((pin >> 4) + 1) |=  _BV(pin & 0xF); // OUT
100         _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
101     }
102 }
103
104 static
105 inline
106 void init_cols(void) {
107     for ( uint8_t i = 0 ; i < NUM_COL_PINS; ++i ) {
108         uint8_t pin = col_pins[i];
109         _SFR_IO8((pin >> 4) + 1) |=  _BV(pin & 0xF); // OUT
110         _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
111     }
112 }
113
114 static
115 inline
116 void select_row(uint8_t current_row) {
117     for ( uint8_t i = 0 ; i < NUM_ROW_PINS; ++i ) {
118         uint8_t pin = row_pins[i] ;
119         if ( check_bit( current_row, i ) ) {
120             _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
121         } else {
122             _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
123         }
124     }
125     wait_us(30) ;
126 }
127
128 static
129 inline
130 void select_col(uint8_t current_col) {
131     for ( uint8_t i = 0 ; i < NUM_COL_PINS; ++i ) {
132         uint8_t pin = col_pins[i] ;
133         if ( check_bit( current_col, i ) ) {
134             _SFR_IO8((pin >> 4) + 2) |=  _BV(pin & 0xF); // HI
135         } else {
136             _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
137         }
138     }
139     wait_us(30) ;
140 }
141
142 static
143 inline
144 uint8_t matrix_strobe(uint8_t col_index) {
145     uint8_t strobe_pin = MATRIX_STROBE_PIN ;
146     uint8_t data_pin   = MATRIX_DATA_PIN   ;
147     
148     // set strobe pin low
149     _SFR_IO8((strobe_pin >> 4) + 2) &=  ~_BV(strobe_pin & 0xF);
150     
151     wait_us(30) ;
152     
153     // read data 
154     uint8_t data = (_SFR_IO8(data_pin >> 4) & _BV(data_pin & 0xF)) ;
155     
156     // set strobe pin hi
157     _SFR_IO8((strobe_pin >> 4) + 2) |= _BV(strobe_pin & 0xF);
158     
159     uint8_t out = data ? (1 << col_index) : 0 ;
160     return out ;
161 }
162
163 static
164 bool matrix_read(uint8_t current_matrix[], uint8_t current_row) {
165     // Store last value of row prior to reading
166     uint8_t last_row_value = current_matrix[current_row];
167
168     // Clear data in matrix row
169     current_matrix[current_row] = 0;
170
171     select_row(current_row);
172
173     // For each col...
174     for(uint8_t col_index = 0; col_index < MATRIX_COLS; ++col_index) {
175
176         select_col(col_index) ;
177         
178         // strobe the matrix
179         // Populate the matrix row with the state of the data pin
180         current_matrix[current_row] |= matrix_strobe(col_index) ;
181     }
182
183     bool test = last_row_value != current_matrix[current_row] ;
184     return test ;
185 }
186
187 __attribute__ ((weak))
188 void matrix_init_quantum(void) {
189     matrix_init_kb();
190 }
191
192 __attribute__ ((weak))
193 void matrix_scan_quantum(void) {
194     matrix_scan_kb();
195 }
196
197 __attribute__ ((weak))
198 void matrix_init_kb(void) {    
199     matrix_init_user();
200 }
201
202 __attribute__ ((weak))
203 void matrix_scan_kb(void) {
204     matrix_scan_user();
205 }
206
207 __attribute__ ((weak))
208 void matrix_init_user(void) {
209 }
210
211 __attribute__ ((weak))
212 void matrix_scan_user(void) {
213 }
214
215 inline
216 uint8_t matrix_rows(void) {
217     return MATRIX_ROWS;
218 }
219
220 inline
221 uint8_t matrix_cols(void) {
222     return MATRIX_COLS;
223 }
224
225 inline
226 uint8_t matrix_get_row(uint8_t row) {
227     return matrix[row];
228 }
229
230 void matrix_init(void) {
231     init_led()    ;   
232     init_rows()   ;
233     init_cols()   ;
234     init_data()   ;
235     init_strobe() ;
236     
237     // initialize matrix state: all keys off
238     for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
239         matrix[i]            = 0;
240 #       if (DEBOUNCING_DELAY > 0)
241         matrix_debounce  [i] = 0;
242 #       endif
243     }
244
245     matrix_init_quantum() ;
246 }
247
248 uint8_t matrix_scan(void) { 
249     for ( uint8_t current_row = 0; current_row < MATRIX_ROWS; ++current_row ) {
250 #       if (DEBOUNCING_DELAY > 0)
251             bool matrix_changed = matrix_read(matrix_debounce, current_row);
252             
253             if (matrix_changed) {
254                 debouncing      = true        ;
255                 debouncing_time = timer_read();
256             }
257                         
258 #       else
259             matrix_read(matrix, current_row);
260 #       endif
261     }
262     
263 #   if (DEBOUNCING_DELAY > 0)
264         if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) {
265             for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
266                 matrix[i] = matrix_debounce[i];
267             }
268             debouncing = false;
269         }
270 #   endif
271
272     matrix_scan_quantum();
273     return 1;
274 }
275
276 void matrix_print(void) {
277     print_matrix_header();
278
279     for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
280         phex(row); print(": ");
281         print_matrix_row(row);
282         print("\n");
283     }
284 }