]> git.donarmstrong.com Git - kiibohd-controller.git/blob - Scan/matrix/matrix_scan.c
Pre Tandy1000 overhaul
[kiibohd-controller.git] / Scan / matrix / matrix_scan.c
1 /* Copyright (C) 2011 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 ) )
43                         
44 #define PIN_SET_COL(pin,scan) \
45                         switch ( scan ) { \
46                         case scanCol: \
47                         case scanRow_powrCol: \
48                         case scanDual: \
49                                 REG_SET(port##pin); break; \
50                         case scanCol_powrRow: REG_SET(ddr##pin); REG_SET(port##pin); break; \
51                         } \
52                         break
53
54 #define PIN_SET_ROW(pin,scan) \
55                         switch ( scan ) { \
56                         case scanRow: \
57                         case scanCol_powrRow: \
58                         case scanDual: \
59                                 REG_SET(port##pin); break; \
60                         case scanRow_powrCol: REG_SET(ddr##pin); REG_SET(port##pin); break; \
61                         } \
62                         break
63
64 #define PIN_CASE(pinLetter) \
65                         case pin##pinLetter##0: \
66                         case pin##pinLetter##1: \
67                         case pin##pinLetter##2: \
68                         case pin##pinLetter##3: \
69                         case pin##pinLetter##4: \
70                         case pin##pinLetter##5: \
71                         case pin##pinLetter##6: \
72                         case pin##pinLetter##7
73
74 // -- Column Scan Macros --
75 #define PIN_TEST_COL(pin) \
76                         scanCode = matrix[row*(MAX_ROW_SIZE+1)+col]; \
77                         if ( scanCode && !( pin & ( 1 << ( matrix[0*(MAX_ROW_SIZE+1)+col] % 10 ) ) ) ) \
78                         { \
79                                 warn_print("YAY!"); \
80                                 detectArray[scanCode]++; \
81                         } \
82                         break
83
84 // -- Row Scan Macros --
85 #define PIN_TEST_ROW(pin) \
86                         scanCode = matrix[row*(MAX_ROW_SIZE+1)+col]; \
87                         if ( scanCode && !( pin & ( 1 << ( matrix[row*(MAX_ROW_SIZE+1)+0] % 10 ) ) ) ) \
88                                 detectArray[scanCode]++; \
89                         break
90
91 // -- Scan Dual Macros --
92 #define PIN_DUALTEST_ROW(pin) \
93                         scanCode = matrix[row*(MAX_ROW_SIZE+1)+col]; \
94                         if ( scanCode \
95                           && !( pin & ( 1 << ( matrix[row*(MAX_ROW_SIZE+1)+0] % 10 ) ) ) \
96                           && detectArray[scanCode] & 0x01 ) \
97                         { \
98                                 detectArray[scanCode]++; \
99                         } \
100                         else \
101                         { \
102                                 if ( detectArray[scanCode] & 0x01 ) \
103                                         detectArray[scanCode]--; \
104                         } \
105                         break
106
107
108
109 // ----- Variables -----
110
111
112
113 // ----- Functions -----
114
115 // Goes through the defined matrix and matrix mode, and sets the initial state of all of the available pins
116 void matrix_pinSetup( uint8_t *matrix, uint8_t scanType )
117 {
118         // Setup the variables
119         uint8_t portA = 0x00;
120         uint8_t portB = 0x00;
121         uint8_t portC = 0x00;
122         uint8_t portD = 0x00;
123         uint8_t portE = 0x00;
124         uint8_t portF = 0x00;
125
126         uint8_t ddrA = 0x00;
127         uint8_t ddrB = 0x00;
128         uint8_t ddrC = 0x00;
129         uint8_t ddrD = 0x00;
130         uint8_t ddrE = 0x00;
131         uint8_t ddrF = 0x00;
132
133         // Loop through all the pin assignments, for the initial pin settings
134         uint16_t row, col;
135
136         // Rows
137         for ( col = 0, row = 1; row < MAX_COL_SIZE + 1; row++ )
138         {
139                 // We can't pass 2D arrays, so just point to the first element and calculate directly
140                 switch ( matrix[row*(MAX_ROW_SIZE+1)+col] )
141                 {
142                 PIN_CASE(A):
143                         PIN_SET_ROW(A, scanType);
144                 PIN_CASE(B):
145                         PIN_SET_ROW(B, scanType);
146                 PIN_CASE(C):
147                         PIN_SET_ROW(C, scanType);
148                 PIN_CASE(D):
149                         PIN_SET_ROW(D, scanType);
150                 PIN_CASE(E):
151                         PIN_SET_ROW(E, scanType);
152                 PIN_CASE(F):
153                         PIN_SET_ROW(F, scanType);
154
155                 default:
156                         continue;
157                 }
158         }
159
160         // Columns
161         for ( col = 1, row = 0; col < (MAX_ROW_SIZE+1) + 1; col++ )
162         {
163                 // We can't pass 2D arrays, so just point to the first element and calculate directly
164                 switch ( matrix[row*(MAX_ROW_SIZE+1)+col] )
165                 {
166                 PIN_CASE(A):
167                         PIN_SET_COL(A, scanType);
168                 PIN_CASE(B):
169                         PIN_SET_COL(B, scanType);
170                 PIN_CASE(C):
171                         PIN_SET_COL(C, scanType);
172                 PIN_CASE(D):
173                         PIN_SET_COL(D, scanType);
174                 PIN_CASE(E):
175                         PIN_SET_COL(E, scanType);
176                 PIN_CASE(F):
177                         PIN_SET_COL(F, scanType);
178
179                 default:
180                         continue;
181                 }
182         }
183
184         // Pin Status
185         if ( scanType == scanMode )
186         {
187                 char tmpStr[6];
188                 info_print("Initial Matrix Pin Setup");
189                 info_print(" ddrA  ddrB  ddrC  ddrD  ddrE  ddrF");
190                 print("      ");
191                 hexToStr_op( ddrA, tmpStr, 2 ); dPrintStrs( "  0x", tmpStr );
192                 hexToStr_op( ddrB, tmpStr, 2 ); dPrintStrs( "  0x", tmpStr );
193                 hexToStr_op( ddrC, tmpStr, 2 ); dPrintStrs( "  0x", tmpStr );
194                 hexToStr_op( ddrD, tmpStr, 2 ); dPrintStrs( "  0x", tmpStr );
195                 hexToStr_op( ddrE, tmpStr, 2 ); dPrintStrs( "  0x", tmpStr );
196                 hexToStr_op( ddrF, tmpStr, 2 ); dPrintStrs( "  0x", tmpStr );
197                 print("\n");
198                 info_print("portA portB portC portD portE portF");
199                 print("      ");
200                 hexToStr_op( portA, tmpStr, 2 ); dPrintStrs( "  0x", tmpStr );
201                 hexToStr_op( portB, tmpStr, 2 ); dPrintStrs( "  0x", tmpStr );
202                 hexToStr_op( portC, tmpStr, 2 ); dPrintStrs( "  0x", tmpStr );
203                 hexToStr_op( portD, tmpStr, 2 ); dPrintStrs( "  0x", tmpStr );
204                 hexToStr_op( portE, tmpStr, 2 ); dPrintStrs( "  0x", tmpStr );
205                 hexToStr_op( portF, tmpStr, 2 ); dPrintStrs( "  0x", tmpStr );
206                 print("\n");
207                 int8ToStr( scanType, tmpStr );
208         }
209
210         // Setting the pins
211 #if defined(__AVR_AT90USB1286__)
212         DDRA = ddrA;
213 #endif
214         DDRB = ddrB;
215         DDRC = ddrC;
216         DDRD = ddrD;
217         DDRE = ddrE;
218         DDRF = ddrF;
219
220 #if defined(__AVR_AT90USB1286__)
221         PORTA = portA;
222 #endif
223         PORTB = portB;
224         PORTC = portC;
225         PORTD = portD;
226         PORTE = portE;
227         PORTF = portF;
228 }
229
230 // Scans the given matrix determined by the scanMode method
231 inline void matrix_scan( uint8_t *matrix, uint8_t *detectArray )
232 {
233         // Loop variables for all modes
234         uint16_t col = 1;
235         uint16_t row = 1;
236         uint16_t scanCode = 0;
237
238
239         // Column Scan and Column Scan, Power Row
240 #if scanMode == scanCol || scanMode == scanCol_powrRow
241         for ( ; row < (MAX_COL_SIZE+1); row++ ) for ( ; col < (MAX_ROW_SIZE+1); col++ )
242         {
243                 // Scan over the pins for each of the columns, and using the pin alias to determine which pin to set
244                 // (e.g. / 10 is for the pin name (A,B,C,etc.) and % 10 is for the position of the pin (A1,A2,etc.))
245                 switch ( matrix[0*(MAX_ROW_SIZE+1)+col] / 10 )
246                                 REG_SET(port##pin); break; \
247                 {
248 #if defined(__AVR_AT90USB1286__)
249                 case 0: // PINA
250                         PIN_TEST_COL(PINA);
251 #endif
252                 case 1: // PINB
253                         PIN_TEST_COL(PINB);
254                 case 2: // PINC
255                         PIN_TEST_COL(PINC);
256                 case 3: // PIND
257                         PIN_TEST_COL(PIND);
258                 case 4: // PINE
259                         PIN_TEST_COL(PINE);
260                 case 5: // PINF
261                         PIN_TEST_COL(PINF);
262                 }
263         }
264 #endif // scanMode
265
266
267         // Row Scan and Row Scan, Power Row
268 #if scanMode == scanRow || scanMode == scanRow_powrCol
269         for ( ; col < (MAX_ROW_SIZE+1); col++ ) for ( ; row < (MAX_COL_SIZE+1); row++ ) 
270         {
271                 // Scan over the pins for each of the rows, and using the pin alias to determine which pin to set
272                 // (e.g. / 10 is for the pin name (A,B,C,etc.) and % 10 is for the position of the pin (A1,A2,etc.))
273                 switch ( matrix[row*(MAX_ROW_SIZE+1)+0] / 10 )
274                 {
275 #if defined(__AVR_AT90USB1286__)
276                 case 0: // PINA
277                         PIN_TEST_ROW(PINA);
278 #endif
279                 case 1: // PINB
280                         PIN_TEST_ROW(PINB);
281                 case 2: // PINC
282                         PIN_TEST_ROW(PINC);
283                 case 3: // PIND
284                         PIN_TEST_ROW(PIND);
285                 case 4: // PINE
286                         PIN_TEST_ROW(PINE);
287                 case 5: // PINF
288                         PIN_TEST_ROW(PINF);
289                 }
290         }
291 #endif // scanMode
292
293
294         // Dual Scan
295 #if scanMode == scanDual
296         // First do a scan of all of the columns, marking each one
297         matrix_pinSetup( matrix, scanCol_powrRow );
298         _delay_us( 1 );
299         for ( ; row < (MAX_COL_SIZE+1); row++ ) for ( ; col < (MAX_ROW_SIZE+1); col++ )
300         {
301                 // Scan over the pins for each of the columns, and using the pin alias to determine which pin to set
302                 // (e.g. / 10 is for the pin name (A,B,C,etc.) and % 10 is for the position of the pin (A1,A2,etc.))
303                 switch ( matrix[0*(MAX_ROW_SIZE+1)+col] / 10 )
304                 {
305 #if defined(__AVR_AT90USB1286__)
306                 case 0: // PINA
307                         PIN_TEST_COL(PINA);
308 #endif
309                 case 1: // PINB
310                         PIN_TEST_COL(PINB);
311                 case 2: // PINC
312                         PIN_TEST_COL(PINC);
313                 case 3: // PIND
314                         PIN_TEST_COL(PIND);
315                 case 4: // PINE
316                         PIN_TEST_COL(PINE);
317                 case 5: // PINF
318                         PIN_TEST_COL(PINF);
319                 }
320         }
321
322         // Next, do a scan of all of the rows, clearing any "vague" keys (only detected on row, but not column, or vice-versa)
323         // And marking any keys that are detected on the row and column
324         matrix_pinSetup( matrix, scanRow_powrCol );
325         _delay_us( 1 );
326         col = 1;
327         row = 1;
328         for ( ; col < (MAX_ROW_SIZE+1); col++ ) for ( ; row < (MAX_COL_SIZE+1); row++ ) 
329         {
330                 // Scan over the pins for each of the rows, and using the pin alias to determine which pin to set
331                 // (e.g. / 10 is for the pin name (A,B,C,etc.) and % 10 is for the position of the pin (A1,A2,etc.))
332                 switch ( matrix[row*(MAX_ROW_SIZE+1)+0] / 10 )
333                 {
334 #if defined(__AVR_AT90USB1286__)
335                 case 0: // PINA
336                         PIN_DUALTEST_ROW(PINA);
337 #endif
338                 case 1: // PINB
339                         PIN_DUALTEST_ROW(PINB);
340                 case 2: // PINC
341                         PIN_DUALTEST_ROW(PINC);
342                 case 3: // PIND
343                         PIN_DUALTEST_ROW(PIND);
344                 case 4: // PINE
345                         PIN_DUALTEST_ROW(PINE);
346                 case 5: // PINF
347                         PIN_DUALTEST_ROW(PINF);
348                 }
349         }
350 #endif
351 }
352