]> git.donarmstrong.com Git - qmk_firmware.git/blob - keyboards/converter/hp_46010a/matrix.c
[Keymap] miryoku layout (#6171)
[qmk_firmware.git] / keyboards / converter / hp_46010a / 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 #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         phex(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....