2011-09-29 06:25:51 +00:00
/* Copyright (C) 2011 by Jacob Alexander
*
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the " Software " ) , to deal
* in the Software without restriction , including without limitation the rights
* to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the Software is
* furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE .
*/
2011-09-30 05:22:19 +00:00
// ----- Includes -----
2011-09-30 08:30:34 +00:00
// AVR Includes
# include <avr/io.h>
2011-11-29 06:20:04 +00:00
# include <util/delay.h>
2011-09-30 08:30:34 +00:00
2011-10-16 03:01:46 +00:00
// Project Includes
# include <print.h>
2011-09-30 05:22:19 +00:00
// Local Includes
2011-10-16 03:01:46 +00:00
# include "matrix_scan.h"
// Matrix Configuration
# include <matrix.h>
2011-09-29 06:25:51 +00:00
2011-09-30 05:22:19 +00:00
// ----- Macros -----
2011-10-17 03:08:37 +00:00
// -- pinSetup Macros --
2012-10-04 19:07:06 +00:00
# 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
# define REG_UNSET(reg) reg &= ~(1 << ( matrix[row*(MAX_ROW_SIZE+1)+col] % 10 ) )
# define PIN_SET(pin,scan,direction) \
switch ( direction ) { \
case columnSet : PIN_SET_COL ( pin , scan ) ; \
case rowSet : PIN_SET_ROW ( pin , scan ) ; \
} \
break
// TODO Only scanCol_powrRow Tested (and powrRow)
2011-11-29 06:20:04 +00:00
# define PIN_SET_COL(pin,scan) \
switch ( scan ) { \
2011-09-29 06:25:51 +00:00
case scanCol : \
2011-11-29 06:20:04 +00:00
case scanRow_powrCol : \
2011-09-29 06:25:51 +00:00
case scanDual : \
REG_SET ( port # # pin ) ; break ; \
2012-10-04 19:07:06 +00:00
case scanCol_powrRow : REG_UNSET ( ddr # # pin ) ; REG_UNSET ( DDR # # pin ) ; \
REG_SET ( port # # pin ) ; REG_SET ( PORT # # pin ) ; break ; \
case powrRow : break ; \
case powrCol : REG_SET ( ddr # # pin ) ; REG_SET ( DDR # # pin ) ; \
REG_SET ( port # # pin ) ; REG_SET ( PORT # # pin ) ; break ; \
2011-09-29 06:25:51 +00:00
} \
break
2012-10-04 19:07:06 +00:00
// TODO Only scanCol_powrRow Tested (and powrRow)
2011-11-29 06:20:04 +00:00
# define PIN_SET_ROW(pin,scan) \
switch ( scan ) { \
2012-10-04 19:07:06 +00:00
case scanRow_powrCol : REG_UNSET ( ddr # # pin ) ; REG_SET ( port # # pin ) ; break ; \
2011-09-29 06:25:51 +00:00
case scanRow : \
case scanDual : \
REG_SET ( port # # pin ) ; break ; \
2012-10-04 19:07:06 +00:00
case scanCol_powrRow : REG_SET ( ddr # # pin ) ; REG_SET ( DDR # # pin ) ; \
REG_UNSET ( port # # pin ) ; REG_UNSET ( PORT # # pin ) ; break ; \
case powrRow : REG_SET ( ddr # # pin ) ; REG_SET ( DDR # # pin ) ; \
REG_SET ( port # # pin ) ; REG_SET ( PORT # # pin ) ; break ; \
case powrCol : break ; \
2011-09-29 06:25:51 +00:00
} \
break
# define PIN_CASE(pinLetter) \
case pin # # pinLetter # # 0 : \
case pin # # pinLetter # # 1 : \
case pin # # pinLetter # # 2 : \
case pin # # pinLetter # # 3 : \
case pin # # pinLetter # # 4 : \
case pin # # pinLetter # # 5 : \
case pin # # pinLetter # # 6 : \
case pin # # pinLetter # # 7
2011-10-17 03:08:37 +00:00
// -- Column Scan Macros --
2011-09-29 06:25:51 +00:00
# define PIN_TEST_COL(pin) \
2011-10-17 03:08:37 +00:00
scanCode = matrix [ row * ( MAX_ROW_SIZE + 1 ) + col ] ; \
if ( scanCode & & ! ( pin & ( 1 < < ( matrix [ 0 * ( MAX_ROW_SIZE + 1 ) + col ] % 10 ) ) ) ) \
2011-11-29 06:20:04 +00:00
{ \
2011-10-17 03:08:37 +00:00
detectArray [ scanCode ] + + ; \
2011-11-29 06:20:04 +00:00
} \
2011-10-17 03:08:37 +00:00
break
// -- Row Scan Macros --
# define PIN_TEST_ROW(pin) \
scanCode = matrix [ row * ( MAX_ROW_SIZE + 1 ) + col ] ; \
if ( scanCode & & ! ( pin & ( 1 < < ( matrix [ row * ( MAX_ROW_SIZE + 1 ) + 0 ] % 10 ) ) ) ) \
2012-10-04 19:07:06 +00:00
{ \
2011-10-17 03:08:37 +00:00
detectArray [ scanCode ] + + ; \
2012-10-04 19:07:06 +00:00
} \
2011-10-17 03:08:37 +00:00
break
// -- Scan Dual Macros --
# define PIN_DUALTEST_ROW(pin) \
scanCode = matrix [ row * ( MAX_ROW_SIZE + 1 ) + col ] ; \
if ( scanCode \
& & ! ( pin & ( 1 < < ( matrix [ row * ( MAX_ROW_SIZE + 1 ) + 0 ] % 10 ) ) ) \
& & detectArray [ scanCode ] & 0x01 ) \
{ \
detectArray [ scanCode ] + + ; \
} \
else \
{ \
if ( detectArray [ scanCode ] & 0x01 ) \
detectArray [ scanCode ] - - ; \
} \
2011-09-29 06:25:51 +00:00
break
2011-09-30 05:22:19 +00:00
// ----- Variables -----
2012-10-04 19:07:06 +00:00
uint8_t showDebug = 0 ;
// Debug Variables for GPIO setting
uint8_t portA = 0x00 ;
uint8_t portB = 0x00 ;
uint8_t portC = 0x00 ;
uint8_t portD = 0x00 ;
uint8_t portE = 0x00 ;
uint8_t portF = 0x00 ;
2011-09-30 05:22:19 +00:00
2012-10-04 19:07:06 +00:00
uint8_t ddrA = 0x00 ;
uint8_t ddrB = 0x00 ;
uint8_t ddrC = 0x00 ;
uint8_t ddrD = 0x00 ;
uint8_t ddrE = 0x00 ;
uint8_t ddrF = 0x00 ;
2011-09-30 05:22:19 +00:00
// ----- Functions -----
2012-11-15 09:28:31 +00:00
void matrix_debugPins ( void ) ;
2012-10-04 19:07:06 +00:00
// Pin Setup Debug
inline void matrix_debugPins ( )
{
char tmpStr [ 6 ] ;
info_print ( " Initial Matrix Pin Setup " ) ;
info_print ( " ddrA ddrB ddrC ddrD ddrE ddrF " ) ;
print ( " " ) ;
hexToStr_op ( ddrA , tmpStr , 2 ) ; dPrintStrs ( " 0x " , tmpStr ) ;
hexToStr_op ( ddrB , tmpStr , 2 ) ; dPrintStrs ( " 0x " , tmpStr ) ;
hexToStr_op ( ddrC , tmpStr , 2 ) ; dPrintStrs ( " 0x " , tmpStr ) ;
hexToStr_op ( ddrD , tmpStr , 2 ) ; dPrintStrs ( " 0x " , tmpStr ) ;
hexToStr_op ( ddrE , tmpStr , 2 ) ; dPrintStrs ( " 0x " , tmpStr ) ;
hexToStr_op ( ddrF , tmpStr , 2 ) ; dPrintStrs ( " 0x " , tmpStr ) ;
print ( " \n " ) ;
info_print ( " portA portB portC portD portE portF " ) ;
print ( " " ) ;
hexToStr_op ( portA , tmpStr , 2 ) ; dPrintStrs ( " 0x " , tmpStr ) ;
hexToStr_op ( portB , tmpStr , 2 ) ; dPrintStrs ( " 0x " , tmpStr ) ;
hexToStr_op ( portC , tmpStr , 2 ) ; dPrintStrs ( " 0x " , tmpStr ) ;
hexToStr_op ( portD , tmpStr , 2 ) ; dPrintStrs ( " 0x " , tmpStr ) ;
hexToStr_op ( portE , tmpStr , 2 ) ; dPrintStrs ( " 0x " , tmpStr ) ;
hexToStr_op ( portF , tmpStr , 2 ) ; dPrintStrs ( " 0x " , tmpStr ) ;
print ( " \n " ) ;
showDebug + + ;
}
2011-09-30 05:22:19 +00:00
2012-10-04 19:07:06 +00:00
// Column Setup
inline void matrix_columnSet ( uint8_t * matrix , uint8_t scanType , uint16_t startIndex , uint16_t colsToIterate )
2011-09-29 06:25:51 +00:00
{
2012-10-04 19:07:06 +00:00
// Calculate the number of pins to iterate over
uint8_t maxColumns = startIndex + colsToIterate - 1 ;
if ( maxColumns > MAX_COL_SIZE )
maxColumns = MAX_COL_SIZE ;
2011-09-29 06:25:51 +00:00
2011-10-16 03:01:46 +00:00
uint16_t row , col ;
2011-09-29 06:25:51 +00:00
2012-10-04 19:07:06 +00:00
// Columns
for ( col = startIndex , row = 0 ; col < = maxColumns ; col + + )
2011-10-16 03:01:46 +00:00
{
// We can't pass 2D arrays, so just point to the first element and calculate directly
switch ( matrix [ row * ( MAX_ROW_SIZE + 1 ) + col ] )
{
2012-10-04 19:07:06 +00:00
# if defined(__AVR_AT90USB1286__)
2011-09-29 06:25:51 +00:00
PIN_CASE ( A ) :
2012-10-04 19:07:06 +00:00
PIN_SET ( A , scanType , columnSet ) ;
# endif
2011-09-29 06:25:51 +00:00
PIN_CASE ( B ) :
2012-10-04 19:07:06 +00:00
PIN_SET ( B , scanType , columnSet ) ;
2011-09-29 06:25:51 +00:00
PIN_CASE ( C ) :
2012-10-04 19:07:06 +00:00
PIN_SET ( C , scanType , columnSet ) ;
2011-09-29 06:25:51 +00:00
PIN_CASE ( D ) :
2012-10-04 19:07:06 +00:00
PIN_SET ( D , scanType , columnSet ) ;
2011-09-29 06:25:51 +00:00
PIN_CASE ( E ) :
2012-10-04 19:07:06 +00:00
PIN_SET ( E , scanType , columnSet ) ;
2011-09-29 06:25:51 +00:00
PIN_CASE ( F ) :
2012-10-04 19:07:06 +00:00
PIN_SET ( F , scanType , columnSet ) ;
2011-09-29 06:25:51 +00:00
default :
continue ;
}
}
2012-10-04 19:07:06 +00:00
}
2011-09-29 06:25:51 +00:00
2012-10-04 19:07:06 +00:00
// Row Setup
inline void matrix_rowSet ( uint8_t * matrix , uint8_t scanType , uint16_t startIndex , uint8_t rowsToIterate )
{
// Calculate the number of pins to iterate over
uint16_t maxRows = startIndex + rowsToIterate - 1 ;
if ( maxRows > MAX_ROW_SIZE )
maxRows = MAX_ROW_SIZE ;
uint16_t row , col ;
// Rows
for ( col = 0 , row = startIndex ; row < = maxRows ; row + + )
2011-10-16 03:01:46 +00:00
{
// We can't pass 2D arrays, so just point to the first element and calculate directly
switch ( matrix [ row * ( MAX_ROW_SIZE + 1 ) + col ] )
{
2012-10-04 19:07:06 +00:00
# if defined(__AVR_AT90USB1286__)
2011-09-29 06:25:51 +00:00
PIN_CASE ( A ) :
2012-10-04 19:07:06 +00:00
PIN_SET ( A , scanType , rowSet ) ;
# endif
2011-09-29 06:25:51 +00:00
PIN_CASE ( B ) :
2012-10-04 19:07:06 +00:00
PIN_SET ( B , scanType , rowSet ) ;
2011-09-29 06:25:51 +00:00
PIN_CASE ( C ) :
2012-10-04 19:07:06 +00:00
PIN_SET ( C , scanType , rowSet ) ;
2011-09-29 06:25:51 +00:00
PIN_CASE ( D ) :
2012-10-04 19:07:06 +00:00
PIN_SET ( D , scanType , rowSet ) ;
2011-09-29 06:25:51 +00:00
PIN_CASE ( E ) :
2012-10-04 19:07:06 +00:00
PIN_SET ( E , scanType , rowSet ) ;
2011-09-29 06:25:51 +00:00
PIN_CASE ( F ) :
2012-10-04 19:07:06 +00:00
PIN_SET ( F , scanType , rowSet ) ;
2011-09-29 06:25:51 +00:00
default :
continue ;
}
}
2012-10-04 19:07:06 +00:00
}
// Goes through the defined matrix and matrix mode, and sets the initial state of all of the available pins
void matrix_pinSetup ( uint8_t * matrix , uint8_t scanType )
{
// Loop through all the pin assignments, for the initial pin settings
matrix_rowSet ( matrix , scanType , 1 , MAX_ROW_SIZE ) ;
matrix_columnSet ( matrix , scanType , 1 , MAX_COL_SIZE ) ;
2011-10-16 03:01:46 +00:00
// Pin Status
2012-10-04 19:07:06 +00:00
if ( showDebug = = 0 ) // Only show once
2011-11-29 06:20:04 +00:00
{
2012-10-04 19:07:06 +00:00
matrix_debugPins ( ) ;
2011-11-29 06:20:04 +00:00
}
2011-09-29 06:25:51 +00:00
}
2011-10-17 03:08:37 +00:00
// Scans the given matrix determined by the scanMode method
2011-10-16 03:01:46 +00:00
inline void matrix_scan ( uint8_t * matrix , uint8_t * detectArray )
2011-09-29 06:25:51 +00:00
{
2011-10-17 03:08:37 +00:00
// Loop variables for all modes
2011-10-16 03:01:46 +00:00
uint16_t col = 1 ;
uint16_t row = 1 ;
2011-10-17 03:08:37 +00:00
uint16_t scanCode = 0 ;
2012-10-04 19:07:06 +00:00
// TODO Only scanCol_powrRow tested
2011-10-17 03:08:37 +00:00
// Column Scan and Column Scan, Power Row
# if scanMode == scanCol || scanMode == scanCol_powrRow
2012-10-04 19:07:06 +00:00
for ( ; row < = MAX_ROW_SIZE ; row + + )
2011-10-16 03:01:46 +00:00
{
2012-10-04 19:07:06 +00:00
// Power each row separately
matrix_rowSet ( matrix , powrRow , row , 1 ) ;
for ( col = 1 ; col < = MAX_COL_SIZE ; col + + )
2011-10-16 03:01:46 +00:00
{
2012-10-04 19:07:06 +00:00
// Scan over the pins for each of the columns, and using the pin alias to determine which pin to set
// (e.g. / 10 is for the pin name (A,B,C,etc.) and % 10 is for the position of the pin (A1,A2,etc.))
switch ( matrix [ 0 * ( MAX_ROW_SIZE + 1 ) + col ] / 10 )
{
2011-10-16 03:01:46 +00:00
# if defined(__AVR_AT90USB1286__)
2012-10-04 19:07:06 +00:00
case 0 : // PINA
PIN_TEST_COL ( PINA ) ;
2011-10-16 03:01:46 +00:00
# endif
2012-10-04 19:07:06 +00:00
case 1 : // PINB
PIN_TEST_COL ( PINB ) ;
case 2 : // PINC
PIN_TEST_COL ( PINC ) ;
case 3 : // PIND
PIN_TEST_COL ( PIND ) ;
case 4 : // PINE
PIN_TEST_COL ( PINE ) ;
case 5 : // PINF
PIN_TEST_COL ( PINF ) ;
}
2011-09-29 06:25:51 +00:00
}
2012-10-04 19:07:06 +00:00
// Unset the row power
matrix_rowSet ( matrix , scanMode , row , 1 ) ;
2011-09-29 06:25:51 +00:00
}
2011-10-17 03:08:37 +00:00
# endif // scanMode
2011-09-29 06:25:51 +00:00
2011-10-17 03:08:37 +00:00
// Row Scan and Row Scan, Power Row
# if scanMode == scanRow || scanMode == scanRow_powrCol
2012-10-04 19:07:06 +00:00
for ( ; col < = MAX_COL_SIZE ; col + + )
2011-10-17 03:08:37 +00:00
{
2012-10-04 19:07:06 +00:00
// Power each column separately
matrix_columnSet ( matrix , powrCol , col , 1 ) ;
for ( row = 1 ; row < = MAX_ROW_SIZE ; row + + )
2011-10-17 03:08:37 +00:00
{
2012-10-04 19:07:06 +00:00
// Scan over the pins for each of the rows, and using the pin alias to determine which pin to set
// (e.g. / 10 is for the pin name (A,B,C,etc.) and % 10 is for the position of the pin (A1,A2,etc.))
switch ( matrix [ row * ( MAX_ROW_SIZE + 1 ) + 0 ] / 10 )
{
2011-10-17 03:08:37 +00:00
# if defined(__AVR_AT90USB1286__)
2012-10-04 19:07:06 +00:00
case 0 : // PINA
PIN_TEST_ROW ( PINA ) ;
2011-09-29 06:25:51 +00:00
# endif
2012-10-04 19:07:06 +00:00
case 1 : // PINB
PIN_TEST_ROW ( PINB ) ;
case 2 : // PINC
PIN_TEST_ROW ( PINC ) ;
case 3 : // PIND
PIN_TEST_ROW ( PIND ) ;
case 4 : // PINE
PIN_TEST_ROW ( PINE ) ;
case 5 : // PINF
PIN_TEST_ROW ( PINF ) ;
}
2011-10-17 03:08:37 +00:00
}
2012-10-04 19:07:06 +00:00
// Unset the column power
matrix_columnSet ( matrix , scanMode , col , 1 ) ;
2011-10-17 03:08:37 +00:00
}
# endif // scanMode
2011-09-29 06:25:51 +00:00
// Dual Scan
# if scanMode == scanDual
2011-10-17 03:08:37 +00:00
// First do a scan of all of the columns, marking each one
2013-01-15 02:43:26 +00:00
//matrix_pinSetup( matrix, scanCol_powrRow, 0, MAX_ROW_SIZE, MAX_COL_SIZE ); TODO
2011-11-29 06:20:04 +00:00
_delay_us ( 1 ) ;
2011-10-17 03:08:37 +00:00
for ( ; row < ( MAX_COL_SIZE + 1 ) ; row + + ) for ( ; col < ( MAX_ROW_SIZE + 1 ) ; col + + )
{
// Scan over the pins for each of the columns, and using the pin alias to determine which pin to set
// (e.g. / 10 is for the pin name (A,B,C,etc.) and % 10 is for the position of the pin (A1,A2,etc.))
switch ( matrix [ 0 * ( MAX_ROW_SIZE + 1 ) + col ] / 10 )
{
# if defined(__AVR_AT90USB1286__)
case 0 : // PINA
PIN_TEST_COL ( PINA ) ;
2011-09-29 06:25:51 +00:00
# endif
2011-10-17 03:08:37 +00:00
case 1 : // PINB
PIN_TEST_COL ( PINB ) ;
case 2 : // PINC
PIN_TEST_COL ( PINC ) ;
case 3 : // PIND
PIN_TEST_COL ( PIND ) ;
case 4 : // PINE
PIN_TEST_COL ( PINE ) ;
case 5 : // PINF
PIN_TEST_COL ( PINF ) ;
}
}
2011-09-29 06:25:51 +00:00
2011-10-17 03:08:37 +00:00
// Next, do a scan of all of the rows, clearing any "vague" keys (only detected on row, but not column, or vice-versa)
// And marking any keys that are detected on the row and column
2013-01-15 02:43:26 +00:00
//matrix_pinSetup( matrix, scanRow_powrCol, 0, MAX_ROW_SIZE, MAX_COL_SIZE ); TODO
2011-11-29 06:20:04 +00:00
_delay_us ( 1 ) ;
2011-10-17 03:08:37 +00:00
col = 1 ;
row = 1 ;
for ( ; col < ( MAX_ROW_SIZE + 1 ) ; col + + ) for ( ; row < ( MAX_COL_SIZE + 1 ) ; row + + )
{
// Scan over the pins for each of the rows, and using the pin alias to determine which pin to set
// (e.g. / 10 is for the pin name (A,B,C,etc.) and % 10 is for the position of the pin (A1,A2,etc.))
switch ( matrix [ row * ( MAX_ROW_SIZE + 1 ) + 0 ] / 10 )
{
# if defined(__AVR_AT90USB1286__)
case 0 : // PINA
PIN_DUALTEST_ROW ( PINA ) ;
# endif
case 1 : // PINB
PIN_DUALTEST_ROW ( PINB ) ;
case 2 : // PINC
PIN_DUALTEST_ROW ( PINC ) ;
case 3 : // PIND
PIN_DUALTEST_ROW ( PIND ) ;
case 4 : // PINE
PIN_DUALTEST_ROW ( PINE ) ;
case 5 : // PINF
PIN_DUALTEST_ROW ( PINF ) ;
}
}
# endif
}