]> git.donarmstrong.com Git - kiibohd-controller.git/blob - Scan/matrix/matrix_scan.c
Move matrix information to a cli command
[kiibohd-controller.git] / Scan / matrix / matrix_scan.c
1 /* Copyright (C) 2011,2014 by Jacob Alexander
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to deal
5  * in the Software without restriction, including without limitation the rights
6  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7  * copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19  * THE SOFTWARE.
20  */
21
22 // ----- Includes -----
23
24 // AVR Includes
25 #include <avr/io.h>
26 #include <util/delay.h>
27
28 // Project Includes
29 #include <print.h>
30
31 // Local Includes
32 #include "matrix_scan.h"
33
34 // Matrix Configuration
35 #include <matrix.h>
36
37
38
39 // ----- Macros -----
40
41 // -- pinSetup Macros --
42 #define REG_SET(reg)    reg |=  (1 << ( matrix[row*(MAX_ROW_SIZE+1)+col] % 10 ) ) // Modulo 10 for the define offset for each pin set 12 or 32 -> shift of 2
43 #define REG_UNSET(reg)  reg &= ~(1 << ( matrix[row*(MAX_ROW_SIZE+1)+col] % 10 ) )
44
45 #define PIN_SET(pin,scan,direction) \
46                         switch ( direction ) { \
47                         case columnSet: PIN_SET_COL(pin,scan); \
48                         case rowSet:    PIN_SET_ROW(pin,scan); \
49                         } \
50                         break
51
52 // TODO Only scanCol_powrRow Tested (and powrRow)
53 #define PIN_SET_COL(pin,scan) \
54                         switch ( scan ) { \
55                         case scanCol: \
56                         case scanRow_powrCol: \
57                         case scanDual: \
58                                 REG_SET(port##pin); break; \
59                         case scanCol_powrRow: REG_UNSET(ddr##pin); REG_UNSET(DDR##pin); \
60                                               REG_SET(port##pin);  REG_SET(PORT##pin); break; \
61                         case powrRow: break; \
62                         case powrCol: REG_SET(ddr##pin);  REG_SET(DDR##pin); \
63                                       REG_SET(port##pin); REG_SET(PORT##pin); break; \
64                         } \
65                         break
66
67 // TODO Only scanCol_powrRow Tested (and powrRow)
68 #define PIN_SET_ROW(pin,scan) \
69                         switch ( scan ) { \
70                         case scanRow_powrCol: REG_UNSET(ddr##pin); REG_SET(port##pin); break; \
71                         case scanRow: \
72                         case scanDual: \
73                                 REG_SET(port##pin); break; \
74                         case scanCol_powrRow: REG_SET(ddr##pin);    REG_SET(DDR##pin); \
75                                               REG_UNSET(port##pin); REG_UNSET(PORT##pin); break; \
76                         case powrRow: REG_SET(ddr##pin);  REG_SET(DDR##pin); \
77                                       REG_SET(port##pin); REG_SET(PORT##pin); break; \
78                         case powrCol: break; \
79                         } \
80                         break
81
82 #define PIN_CASE(pinLetter) \
83                         case pin##pinLetter##0: \
84                         case pin##pinLetter##1: \
85                         case pin##pinLetter##2: \
86                         case pin##pinLetter##3: \
87                         case pin##pinLetter##4: \
88                         case pin##pinLetter##5: \
89                         case pin##pinLetter##6: \
90                         case pin##pinLetter##7
91
92 // -- Column Scan Macros --
93 #define PIN_TEST_COL(pin) \
94                         scanCode = matrix[row*(MAX_ROW_SIZE+1)+col]; \
95                         if ( scanCode && !( pin & ( 1 << ( matrix[0*(MAX_ROW_SIZE+1)+col] % 10 ) ) ) ) \
96                         { \
97                                 detectArray[scanCode]++; \
98                         } \
99                         break
100
101 // -- Row Scan Macros --
102 #define PIN_TEST_ROW(pin) \
103                         scanCode = matrix[row*(MAX_ROW_SIZE+1)+col]; \
104                         if ( scanCode && !( pin & ( 1 << ( matrix[row*(MAX_ROW_SIZE+1)+0] % 10 ) ) ) ) \
105                         { \
106                                 detectArray[scanCode]++; \
107                         } \
108                         break
109
110 // -- Scan Dual Macros --
111 #define PIN_DUALTEST_ROW(pin) \
112                         scanCode = matrix[row*(MAX_ROW_SIZE+1)+col]; \
113                         if ( scanCode \
114                           && !( pin & ( 1 << ( matrix[row*(MAX_ROW_SIZE+1)+0] % 10 ) ) ) \
115                           && detectArray[scanCode] & 0x01 ) \
116                         { \
117                                 detectArray[scanCode]++; \
118                         } \
119                         else \
120                         { \
121                                 if ( detectArray[scanCode] & 0x01 ) \
122                                         detectArray[scanCode]--; \
123                         } \
124                         break
125
126
127
128 // ----- Variables -----
129 uint8_t showDebug = 0;
130
131 // Debug Variables for GPIO setting
132 uint8_t portA = 0x00;
133 uint8_t portB = 0x00;
134 uint8_t portC = 0x00;
135 uint8_t portD = 0x00;
136 uint8_t portE = 0x00;
137 uint8_t portF = 0x00;
138
139 uint8_t ddrA = 0x00;
140 uint8_t ddrB = 0x00;
141 uint8_t ddrC = 0x00;
142 uint8_t ddrD = 0x00;
143 uint8_t ddrE = 0x00;
144 uint8_t ddrF = 0x00;
145
146
147 // ----- Functions -----
148 void matrix_debugPins(void);
149
150 // Pin Setup Debug
151 inline void matrix_debugPins()
152 {
153         char tmpStr[6];
154         info_print("Initial Matrix Pin Setup");
155         info_print(" ddrA  ddrB  ddrC  ddrD  ddrE  ddrF");
156         print("      ");
157         hexToStr_op( ddrA, tmpStr, 2 ); dPrintStrs( "  0x", tmpStr );
158         hexToStr_op( ddrB, tmpStr, 2 ); dPrintStrs( "  0x", tmpStr );
159         hexToStr_op( ddrC, tmpStr, 2 ); dPrintStrs( "  0x", tmpStr );
160         hexToStr_op( ddrD, tmpStr, 2 ); dPrintStrs( "  0x", tmpStr );
161         hexToStr_op( ddrE, tmpStr, 2 ); dPrintStrs( "  0x", tmpStr );
162         hexToStr_op( ddrF, tmpStr, 2 ); dPrintStrs( "  0x", tmpStr );
163         print("\n");
164         info_print("portA portB portC portD portE portF");
165         print("      ");
166         hexToStr_op( portA, tmpStr, 2 ); dPrintStrs( "  0x", tmpStr );
167         hexToStr_op( portB, tmpStr, 2 ); dPrintStrs( "  0x", tmpStr );
168         hexToStr_op( portC, tmpStr, 2 ); dPrintStrs( "  0x", tmpStr );
169         hexToStr_op( portD, tmpStr, 2 ); dPrintStrs( "  0x", tmpStr );
170         hexToStr_op( portE, tmpStr, 2 ); dPrintStrs( "  0x", tmpStr );
171         hexToStr_op( portF, tmpStr, 2 ); dPrintStrs( "  0x", tmpStr );
172         print("\n");
173
174         showDebug++;
175 }
176
177
178 // Column Setup
179 inline void matrix_columnSet( uint8_t *matrix, uint8_t scanType, uint16_t startIndex, uint16_t colsToIterate )
180 {
181         // Calculate the number of pins to iterate over
182         uint8_t maxColumns = startIndex + colsToIterate - 1;
183         if ( maxColumns > MAX_COL_SIZE )
184                 maxColumns = MAX_COL_SIZE;
185
186         uint16_t row, col;
187
188         // Columns
189         for ( col = startIndex, row = 0; col <= maxColumns; col++ )
190         {
191                 // We can't pass 2D arrays, so just point to the first element and calculate directly
192                 switch ( matrix[row*(MAX_ROW_SIZE+1)+col] )
193                 {
194 #if defined(__AVR_AT90USB1286__)
195                 PIN_CASE(A):
196                         PIN_SET(A, scanType, columnSet);
197 #endif
198                 PIN_CASE(B):
199                         PIN_SET(B, scanType, columnSet);
200                 PIN_CASE(C):
201                         PIN_SET(C, scanType, columnSet);
202                 PIN_CASE(D):
203                         PIN_SET(D, scanType, columnSet);
204                 PIN_CASE(E):
205                         PIN_SET(E, scanType, columnSet);
206                 PIN_CASE(F):
207                         PIN_SET(F, scanType, columnSet);
208
209                 default:
210                         continue;
211                 }
212         }
213 }
214
215 // Row Setup
216 inline void matrix_rowSet( uint8_t *matrix, uint8_t scanType, uint16_t startIndex, uint8_t rowsToIterate )
217 {
218         // Calculate the number of pins to iterate over
219         uint16_t maxRows = startIndex + rowsToIterate - 1;
220         if ( maxRows > MAX_ROW_SIZE )
221                 maxRows = MAX_ROW_SIZE;
222
223         uint16_t row, col;
224
225         // Rows
226         for ( col = 0, row = startIndex; row <= maxRows; row++ )
227         {
228                 // We can't pass 2D arrays, so just point to the first element and calculate directly
229                 switch ( matrix[row*(MAX_ROW_SIZE+1)+col] )
230                 {
231 #if defined(__AVR_AT90USB1286__)
232                 PIN_CASE(A):
233                         PIN_SET(A, scanType, rowSet);
234 #endif
235                 PIN_CASE(B):
236                         PIN_SET(B, scanType, rowSet);
237                 PIN_CASE(C):
238                         PIN_SET(C, scanType, rowSet);
239                 PIN_CASE(D):
240                         PIN_SET(D, scanType, rowSet);
241                 PIN_CASE(E):
242                         PIN_SET(E, scanType, rowSet);
243                 PIN_CASE(F):
244                         PIN_SET(F, scanType, rowSet);
245
246                 default:
247                         continue;
248                 }
249         }
250 }
251
252
253 // Goes through the defined matrix and matrix mode, and sets the initial state of all of the available pins
254 void matrix_pinSetup( uint8_t *matrix, uint8_t scanType )
255 {
256         // Loop through all the pin assignments, for the initial pin settings
257         matrix_rowSet   ( matrix, scanType, 1, MAX_ROW_SIZE );
258         matrix_columnSet( matrix, scanType, 1, MAX_COL_SIZE );
259
260         // Pin Status
261         if ( showDebug == 0 ) // Only show once
262         {
263                 matrix_debugPins();
264         }       
265 }
266
267 // Scans the given matrix determined by the scanMode method
268 inline void matrix_scan( uint8_t *matrix, uint8_t *detectArray )
269 {
270         // Loop variables for all modes
271         uint16_t col = 1;
272         uint16_t row = 1;
273         uint16_t scanCode = 0;
274
275
276         // TODO Only scanCol_powrRow tested
277         // Column Scan and Column Scan, Power Row
278 #if scanMode == scanCol || scanMode == scanCol_powrRow
279         for ( ; row <= MAX_ROW_SIZE; row++ )
280         {
281                 // Power each row separately
282                 matrix_rowSet( matrix, powrRow, row, 1 );
283
284                 for ( col = 1; col <= MAX_COL_SIZE; col++ )
285                 {
286                         // Scan over the pins for each of the columns, and using the pin alias to determine which pin to set
287                         // (e.g. / 10 is for the pin name (A,B,C,etc.) and % 10 is for the position of the pin (A1,A2,etc.))
288                         switch ( matrix[0*(MAX_ROW_SIZE+1)+col] / 10 )
289                         {
290 #if defined(__AVR_AT90USB1286__)
291                         case 0: // PINA
292                                 PIN_TEST_COL(PINA);
293 #endif
294                         case 1: // PINB
295                                 PIN_TEST_COL(PINB);
296                         case 2: // PINC
297                                 PIN_TEST_COL(PINC);
298                         case 3: // PIND
299                                 PIN_TEST_COL(PIND);
300                         case 4: // PINE
301                                 PIN_TEST_COL(PINE);
302                         case 5: // PINF
303                                 PIN_TEST_COL(PINF);
304                         }
305                 }
306
307                 // Unset the row power
308                 matrix_rowSet( matrix, scanMode, row, 1 );
309         }
310 #endif // scanMode
311
312
313         // Row Scan and Row Scan, Power Row
314 #if scanMode == scanRow || scanMode == scanRow_powrCol
315         for ( ; col <= MAX_COL_SIZE; col++ )
316         {
317                 // Power each column separately
318                 matrix_columnSet( matrix, powrCol, col, 1 );
319
320                 for ( row = 1; row <= MAX_ROW_SIZE; row++ )
321                 {
322                         // Scan over the pins for each of the rows, and using the pin alias to determine which pin to set
323                         // (e.g. / 10 is for the pin name (A,B,C,etc.) and % 10 is for the position of the pin (A1,A2,etc.))
324                         switch ( matrix[row*(MAX_ROW_SIZE+1)+0] / 10 )
325                         {
326 #if defined(__AVR_AT90USB1286__)
327                         case 0: // PINA
328                                 PIN_TEST_ROW(PINA);
329 #endif
330                         case 1: // PINB
331                                 PIN_TEST_ROW(PINB);
332                         case 2: // PINC
333                                 PIN_TEST_ROW(PINC);
334                         case 3: // PIND
335                                 PIN_TEST_ROW(PIND);
336                         case 4: // PINE
337                                 PIN_TEST_ROW(PINE);
338                         case 5: // PINF
339                                 PIN_TEST_ROW(PINF);
340                         }
341                 }
342
343                 // Unset the column power
344                 matrix_columnSet( matrix, scanMode, col, 1 );
345         }
346 #endif // scanMode
347
348
349         // Dual Scan
350 #if scanMode == scanDual
351         // First do a scan of all of the columns, marking each one
352         //matrix_pinSetup( matrix, scanCol_powrRow, 0, MAX_ROW_SIZE, MAX_COL_SIZE ); TODO
353         _delay_us( 1 );
354         for ( ; row < (MAX_COL_SIZE+1); row++ ) for ( ; col < (MAX_ROW_SIZE+1); col++ )
355         {
356                 // Scan over the pins for each of the columns, and using the pin alias to determine which pin to set
357                 // (e.g. / 10 is for the pin name (A,B,C,etc.) and % 10 is for the position of the pin (A1,A2,etc.))
358                 switch ( matrix[0*(MAX_ROW_SIZE+1)+col] / 10 )
359                 {
360 #if defined(__AVR_AT90USB1286__)
361                 case 0: // PINA
362                         PIN_TEST_COL(PINA);
363 #endif
364                 case 1: // PINB
365                         PIN_TEST_COL(PINB);
366                 case 2: // PINC
367                         PIN_TEST_COL(PINC);
368                 case 3: // PIND
369                         PIN_TEST_COL(PIND);
370                 case 4: // PINE
371                         PIN_TEST_COL(PINE);
372                 case 5: // PINF
373                         PIN_TEST_COL(PINF);
374                 }
375         }
376
377         // Next, do a scan of all of the rows, clearing any "vague" keys (only detected on row, but not column, or vice-versa)
378         // And marking any keys that are detected on the row and column
379         //matrix_pinSetup( matrix, scanRow_powrCol, 0, MAX_ROW_SIZE, MAX_COL_SIZE ); TODO
380         _delay_us( 1 );
381         col = 1;
382         row = 1;
383         for ( ; col < (MAX_ROW_SIZE+1); col++ ) for ( ; row < (MAX_COL_SIZE+1); row++ ) 
384         {
385                 // Scan over the pins for each of the rows, and using the pin alias to determine which pin to set
386                 // (e.g. / 10 is for the pin name (A,B,C,etc.) and % 10 is for the position of the pin (A1,A2,etc.))
387                 switch ( matrix[row*(MAX_ROW_SIZE+1)+0] / 10 )
388                 {
389 #if defined(__AVR_AT90USB1286__)
390                 case 0: // PINA
391                         PIN_DUALTEST_ROW(PINA);
392 #endif
393                 case 1: // PINB
394                         PIN_DUALTEST_ROW(PINB);
395                 case 2: // PINC
396                         PIN_DUALTEST_ROW(PINC);
397                 case 3: // PIND
398                         PIN_DUALTEST_ROW(PIND);
399                 case 4: // PINE
400                         PIN_DUALTEST_ROW(PINE);
401                 case 5: // PINF
402                         PIN_DUALTEST_ROW(PINF);
403                 }
404         }
405 #endif
406 }
407