diff options
Diffstat (limited to 'keyboards/converter/hp_46010a/matrix.c')
-rw-r--r-- | keyboards/converter/hp_46010a/matrix.c | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/keyboards/converter/hp_46010a/matrix.c b/keyboards/converter/hp_46010a/matrix.c new file mode 100644 index 000000000..03fcb2424 --- /dev/null +++ b/keyboards/converter/hp_46010a/matrix.c | |||
@@ -0,0 +1,244 @@ | |||
1 | /* | ||
2 | Copyright 2018 listofoptions <[email protected]> | ||
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 | #include <LUFA/Drivers/Peripheral/SPI.h> | ||
33 | |||
34 | #include "config.h" | ||
35 | |||
36 | |||
37 | #ifndef DEBOUNCE | ||
38 | # define DEBOUNCE 5 | ||
39 | #endif | ||
40 | |||
41 | #if ( DEBOUNCE > 0 ) | ||
42 | static uint16_t debouncing_time ; | ||
43 | static bool debouncing = false ; | ||
44 | #endif | ||
45 | |||
46 | static uint8_t matrix [MATRIX_ROWS] = {0}; | ||
47 | |||
48 | #if ( DEBOUNCE > 0 ) | ||
49 | static uint8_t matrix_debounce_old [MATRIX_ROWS] = {0}; | ||
50 | static uint8_t matrix_debounce_new [MATRIX_ROWS] = {0}; | ||
51 | #endif | ||
52 | |||
53 | __attribute__ ((weak)) | ||
54 | void matrix_init_quantum(void) { | ||
55 | matrix_init_kb(); | ||
56 | } | ||
57 | |||
58 | __attribute__ ((weak)) | ||
59 | void matrix_scan_quantum(void) { | ||
60 | matrix_scan_kb(); | ||
61 | } | ||
62 | |||
63 | __attribute__ ((weak)) | ||
64 | void matrix_init_kb(void) { | ||
65 | matrix_init_user(); | ||
66 | } | ||
67 | |||
68 | __attribute__ ((weak)) | ||
69 | void matrix_scan_kb(void) { | ||
70 | matrix_scan_user(); | ||
71 | } | ||
72 | |||
73 | __attribute__ ((weak)) | ||
74 | void matrix_init_user(void) { | ||
75 | } | ||
76 | |||
77 | __attribute__ ((weak)) | ||
78 | void matrix_scan_user(void) { | ||
79 | } | ||
80 | |||
81 | // the keyboard's internal wiring is such that the inputs to the logic are | ||
82 | // a clock signal, and a reset line. | ||
83 | // the output is a single output pin. im bitbanging here, but the SPI controller | ||
84 | // would work normally | ||
85 | // | ||
86 | // the device functions, by using the clock signal to count 128 bits, the lower | ||
87 | // 3 bits of this 7 bit counter are tied to a 1-of-8 multiplexer, this forms | ||
88 | // the columns. | ||
89 | // the upper 4 bits form the rows, and are decoded using bcd to decimal | ||
90 | // decoders, so that 14 out of 16 of the outputs are wired to the rows of the | ||
91 | // matrix. each switch has a diode, such that the row signal feeds into the | ||
92 | // switch, and then into the diode, then into one of the columns into the | ||
93 | // matrix. the reset pin can be used to reset the entire counter. | ||
94 | |||
95 | #define RESET _BV(PB0) | ||
96 | #define SCLK _BV(PB1) | ||
97 | #define SDATA _BV(PB3) | ||
98 | #define LED _BV(PD6) | ||
99 | |||
100 | inline | ||
101 | static | ||
102 | void SCLK_increment(void) { | ||
103 | PORTB &= ~SCLK ; | ||
104 | _delay_us( 4 ) ; // make sure the line is stable | ||
105 | PORTB |= SCLK ; | ||
106 | _delay_us( 4 ) ; | ||
107 | |||
108 | return ; | ||
109 | } | ||
110 | |||
111 | inline | ||
112 | static | ||
113 | void Matrix_Reset(void) { | ||
114 | PORTB |= RESET ; | ||
115 | _delay_us( 4 ) ; // make sure the line is stable | ||
116 | PORTB &= ~RESET ; | ||
117 | |||
118 | return ; | ||
119 | } | ||
120 | |||
121 | inline | ||
122 | static | ||
123 | uint8_t Matrix_ReceiveByte (void) { | ||
124 | uint8_t received = 0 ; | ||
125 | uint8_t temp = 0 ; | ||
126 | for ( uint8_t bit = 0; bit < MATRIX_COLS; ++bit ) { | ||
127 | // toggle the clock | ||
128 | SCLK_increment(); | ||
129 | temp = (PINB & SDATA) << 4 ; | ||
130 | received |= temp >> bit ; | ||
131 | } | ||
132 | |||
133 | return received ; | ||
134 | } | ||
135 | |||
136 | inline | ||
137 | static | ||
138 | void Matrix_ThrowByte(void) { | ||
139 | // we use MATRIX_COLS - 1 here because that would put us at 7 clocks | ||
140 | for ( uint8_t bit = 0; bit < MATRIX_COLS - 1; ++bit ) { | ||
141 | // toggle the clock | ||
142 | SCLK_increment(); | ||
143 | } | ||
144 | |||
145 | return ; | ||
146 | } | ||
147 | |||
148 | void matrix_init () { | ||
149 | // debug_matrix = 1; | ||
150 | // PB0 (SS) and PB1 (SCLK) set to outputs | ||
151 | DDRB |= RESET | SCLK ; | ||
152 | // PB2, is unused, and PB3 is our serial input | ||
153 | DDRB &= ~SDATA ; | ||
154 | |||
155 | // SS is reset for this board, and is active High | ||
156 | // SCLK is the serial clock and is active High | ||
157 | PORTB &= ~RESET ; | ||
158 | PORTB |= SCLK ; | ||
159 | |||
160 | // led pin | ||
161 | DDRD |= LED ; | ||
162 | PORTD &= ~LED ; | ||
163 | |||
164 | matrix_init_quantum(); | ||
165 | |||
166 | //toggle reset, to put the keyboard logic into a known state | ||
167 | Matrix_Reset() ; | ||
168 | } | ||
169 | |||
170 | uint8_t matrix_scan(void) { | ||
171 | |||
172 | // the first byte of the keyboard's output data can be ignored | ||
173 | Matrix_ThrowByte(); | ||
174 | |||
175 | #if ( DEBOUNCE > 0 ) | ||
176 | |||
177 | for ( uint8_t row = 0 ; row < MATRIX_ROWS ; ++row ) { | ||
178 | //transfer old debouncing values | ||
179 | matrix_debounce_old[row] = matrix_debounce_new[row] ; | ||
180 | // read new key-states in | ||
181 | matrix_debounce_new[row] = Matrix_ReceiveByte() ; | ||
182 | |||
183 | if ( matrix_debounce_new[row] != matrix_debounce_old[row] ) { | ||
184 | debouncing = true ; | ||
185 | debouncing_time = timer_read() ; | ||
186 | } | ||
187 | } | ||
188 | |||
189 | #else | ||
190 | // without debouncing we simply just read in the raw matrix | ||
191 | for ( uint8_t row = 0 ; row < MATRIX_ROWS ; ++row ) { | ||
192 | matrix[row] = Matrix_ReceiveByte ; | ||
193 | } | ||
194 | #endif | ||
195 | |||
196 | |||
197 | #if ( DEBOUNCE > 0 ) | ||
198 | if ( debouncing && ( timer_elapsed( debouncing_time ) > DEBOUNCE ) ) { | ||
199 | |||
200 | for ( uint8_t row = 0 ; row < MATRIX_ROWS ; ++row ) { | ||
201 | matrix[row] = matrix_debounce_new[row] ; | ||
202 | } | ||
203 | |||
204 | debouncing = false ; | ||
205 | } | ||
206 | #endif | ||
207 | Matrix_Reset() ; | ||
208 | |||
209 | matrix_scan_quantum() ; | ||
210 | return 1; | ||
211 | } | ||
212 | |||
213 | inline | ||
214 | uint8_t matrix_get_row( uint8_t row ) { | ||
215 | return matrix[row]; | ||
216 | } | ||
217 | |||
218 | void matrix_print(void) | ||
219 | { | ||
220 | print("\nr/c 01234567\n"); | ||
221 | |||
222 | for (uint8_t row = 0; row < MATRIX_ROWS; row++) { | ||
223 | print_hex8(row); print(": "); | ||
224 | print_bin_reverse8(matrix_get_row(row)); | ||
225 | print("\n"); | ||
226 | } | ||
227 | } | ||
228 | |||
229 | inline | ||
230 | uint8_t matrix_rows(void) { | ||
231 | return MATRIX_ROWS; | ||
232 | } | ||
233 | |||
234 | inline | ||
235 | uint8_t matrix_cols(void) { | ||
236 | return MATRIX_COLS; | ||
237 | } | ||
238 | |||
239 | // as an aside, I used the M0110 converter: | ||
240 | // tmk_core/common/keyboard.c, quantum/matrix.c, and the project layout of the planck | ||
241 | // the online ducmentation starting from : | ||
242 | // https://docs.qmk.fm/#/config_options | ||
243 | // https://docs.qmk.fm/#/understanding_qmk | ||
244 | // and probably a few i forgot.... \ No newline at end of file | ||