1 /* Copyright (C) 2011 by Jacob Alexander
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:
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
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
22 // ----- Includes -----
26 #include <util/delay.h>
32 #include "matrix_scan.h"
34 // Matrix Configuration
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 ) )
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); \
52 // TODO Only scanCol_powrRow Tested (and powrRow)
53 #define PIN_SET_COL(pin,scan) \
56 case scanRow_powrCol: \
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; \
67 // TODO Only scanCol_powrRow Tested (and powrRow)
68 #define PIN_SET_ROW(pin,scan) \
70 case scanRow_powrCol: REG_UNSET(ddr##pin); REG_SET(port##pin); break; \
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; \
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
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 ) ) ) ) \
97 detectArray[scanCode]++; \
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 ) ) ) ) \
106 detectArray[scanCode]++; \
110 // -- Scan Dual Macros --
111 #define PIN_DUALTEST_ROW(pin) \
112 scanCode = matrix[row*(MAX_ROW_SIZE+1)+col]; \
114 && !( pin & ( 1 << ( matrix[row*(MAX_ROW_SIZE+1)+0] % 10 ) ) ) \
115 && detectArray[scanCode] & 0x01 ) \
117 detectArray[scanCode]++; \
121 if ( detectArray[scanCode] & 0x01 ) \
122 detectArray[scanCode]--; \
128 // ----- Variables -----
129 uint8_t showDebug = 0;
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;
147 // ----- Functions -----
148 void matrix_debugPins(void);
151 inline void matrix_debugPins()
154 info_print("Initial Matrix Pin Setup");
155 info_print(" ddrA ddrB ddrC ddrD ddrE ddrF");
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 );
164 info_print("portA portB portC portD portE portF");
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 );
179 inline void matrix_columnSet( uint8_t *matrix, uint8_t scanType, uint16_t startIndex, uint16_t colsToIterate )
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;
189 for ( col = startIndex, row = 0; col <= maxColumns; col++ )
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] )
194 #if defined(__AVR_AT90USB1286__)
196 PIN_SET(A, scanType, columnSet);
199 PIN_SET(B, scanType, columnSet);
201 PIN_SET(C, scanType, columnSet);
203 PIN_SET(D, scanType, columnSet);
205 PIN_SET(E, scanType, columnSet);
207 PIN_SET(F, scanType, columnSet);
216 inline void matrix_rowSet( uint8_t *matrix, uint8_t scanType, uint16_t startIndex, uint8_t rowsToIterate )
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;
226 for ( col = 0, row = startIndex; row <= maxRows; row++ )
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] )
231 #if defined(__AVR_AT90USB1286__)
233 PIN_SET(A, scanType, rowSet);
236 PIN_SET(B, scanType, rowSet);
238 PIN_SET(C, scanType, rowSet);
240 PIN_SET(D, scanType, rowSet);
242 PIN_SET(E, scanType, rowSet);
244 PIN_SET(F, scanType, rowSet);
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 )
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 );
261 if ( showDebug == 0 ) // Only show once
267 // Scans the given matrix determined by the scanMode method
268 inline void matrix_scan( uint8_t *matrix, uint8_t *detectArray )
270 // Loop variables for all modes
273 uint16_t scanCode = 0;
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++ )
281 // Power each row separately
282 matrix_rowSet( matrix, powrRow, row, 1 );
284 for ( col = 1; col <= MAX_COL_SIZE; col++ )
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 )
290 #if defined(__AVR_AT90USB1286__)
307 // Unset the row power
308 matrix_rowSet( matrix, scanMode, row, 1 );
313 // Row Scan and Row Scan, Power Row
314 #if scanMode == scanRow || scanMode == scanRow_powrCol
315 for ( ; col <= MAX_COL_SIZE; col++ )
317 // Power each column separately
318 matrix_columnSet( matrix, powrCol, col, 1 );
320 for ( row = 1; row <= MAX_ROW_SIZE; row++ )
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 )
326 #if defined(__AVR_AT90USB1286__)
343 // Unset the column power
344 matrix_columnSet( matrix, scanMode, col, 1 );
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
354 for ( ; row < (MAX_COL_SIZE+1); row++ ) for ( ; col < (MAX_ROW_SIZE+1); col++ )
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 )
360 #if defined(__AVR_AT90USB1286__)
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
383 for ( ; col < (MAX_ROW_SIZE+1); col++ ) for ( ; row < (MAX_COL_SIZE+1); row++ )
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 )
389 #if defined(__AVR_AT90USB1286__)
391 PIN_DUALTEST_ROW(PINA);
394 PIN_DUALTEST_ROW(PINB);
396 PIN_DUALTEST_ROW(PINC);
398 PIN_DUALTEST_ROW(PIND);
400 PIN_DUALTEST_ROW(PINE);
402 PIN_DUALTEST_ROW(PINF);