@ -26,32 +26,46 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
# include "util.h"
# include "matrix.h"
# ifdef MATRIX_HAS_GHOST
# error "The universal matrix.c file cannot be used for this keyboard."
# endif
/* Set 0 if debouncing isn't needed */
/*
* This constant define not debouncing time in msecs , but amount of matrix
* scan loops which should be made to get stable debounced results .
*
* On Ergodox matrix scan rate is relatively low , because of slow I2C .
* Now it ' s only 317 scans / second , or about 3.15 msec / scan .
* According to Cherry specs , debouncing time is 5 msec .
*
* And so , there is no sense to have DEBOUNCE higher than 2.
*/
# ifndef DEBOUNCING_DELAY
# define DEBOUNCING_DELAY 5
# endif
static uint8_t debouncing = DEBOUNCING_DELAY ;
static const uint8_t row_pins [ MATRIX_ROWS ] = MATRIX_ROW_PINS ;
static const uint8_t col_pins [ MATRIX_COLS ] = MATRIX_COL_PINS ;
/* matrix state */
# if DIODE_DIRECTION == COL2ROW
/* matrix state(1:on, 0:off) */
static matrix_row_t matrix [ MATRIX_ROWS ] ;
# else
static matrix_col_t matrix [ MATRIX_COLS ] ;
static matrix_row_t matrix_debouncing [ MATRIX_ROWS ] ;
# if DIODE_DIRECTION == ROW2COL
static matrix_row_t matrix_reversed [ MATRIX_COLS ] ;
static matrix_row_t matrix_reversed_debouncing [ MATRIX_COLS ] ;
# endif
static int8_t debouncing_delay = - 1 ;
# if DIODE_DIRECTION == COL2ROW
static void toggle_row ( uint8_t row ) ;
static matrix_row_t read_cols ( void ) ;
# if MATRIX_COLS > 16
# define SHIFTER 1UL
# else
static void toggle_col ( uint8_t col ) ;
static matrix_col_t read_rows ( void ) ;
# define SHIFTER 1
# endif
static matrix_row_t read_cols ( void ) ;
static void init_cols ( void ) ;
static void unselect_rows ( void ) ;
static void select_row ( uint8_t row ) ;
__attribute__ ( ( weak ) )
void matrix_init_quantum ( void ) {
matrix_init_kb ( ) ;
@ -80,10 +94,12 @@ __attribute__ ((weak))
void matrix_scan_user ( void ) {
}
inline
uint8_t matrix_rows ( void ) {
return MATRIX_ROWS ;
}
inline
uint8_t matrix_cols ( void ) {
return MATRIX_COLS ;
}
@ -113,161 +129,179 @@ uint8_t matrix_cols(void) {
// }
void matrix_init ( void ) {
/* frees PORTF by setting the JTD bit twice within four cycles */
// To use PORTF disable JTAG with writing JTD bit twice within four cycles.
# ifdef __AVR_ATmega32U4__
MCUCR | = _BV ( JTD ) ;
MCUCR | = _BV ( JTD ) ;
# endif
/* initializes the I/O pins */
# if DIODE_DIRECTION == COL2ROW
for ( int8_t r = MATRIX_ROWS - 1 ; r > = 0 ; - - r ) {
/* DDRxn */
_SFR_IO8 ( ( row_pins [ r ] > > 4 ) + 1 ) | = _BV ( row_pins [ r ] & 0xF ) ;
toggle_row ( r ) ;
}
for ( int8_t c = MATRIX_COLS - 1 ; c > = 0 ; - - c ) {
/* PORTxn */
_SFR_IO8 ( ( col_pins [ c ] > > 4 ) + 2 ) | = _BV ( col_pins [ c ] & 0xF ) ;
}
# else
for ( int8_t c = MATRIX_COLS - 1 ; c > = 0 ; - - c ) {
/* DDRxn */
_SFR_IO8 ( ( col_pins [ c ] > > 4 ) + 1 ) | = _BV ( col_pins [ c ] & 0xF ) ;
toggle_col ( c ) ;
}
for ( int8_t r = MATRIX_ROWS - 1 ; r > = 0 ; - - r ) {
/* PORTxn */
_SFR_IO8 ( ( row_pins [ r ] > > 4 ) + 2 ) | = _BV ( row_pins [ r ] & 0xF ) ;
// initialize row and col
unselect_rows ( ) ;
init_cols ( ) ;
// initialize matrix state: all keys off
for ( uint8_t i = 0 ; i < MATRIX_ROWS ; i + + ) {
matrix [ i ] = 0 ;
matrix_debouncing [ i ] = 0 ;
}
# endif
matrix_init_quantum ( ) ;
}
uint8_t matrix_scan ( void )
{
# if DIODE_DIRECTION == COL2ROW
uint8_t matrix_scan ( void ) {
static matrix_row_t debouncing_matrix [ MATRIX_ROWS ] ;
for ( int8_t r = MATRIX_ROWS - 1 ; r > = 0 ; - - r ) {
toggle_row ( r ) ;
matrix_row_t state = read_cols ( ) ;
if ( debouncing_matrix [ r ] ! = state ) {
debouncing_matrix [ r ] = state ;
debouncing_delay = DEBOUNCING_DELAY ;
}
toggle_row ( r ) ;
}
if ( debouncing_delay > = 0 ) {
dprintf ( " Debouncing delay remaining: %X \n " , debouncing_delay ) ;
- - debouncing_delay ;
if ( debouncing_delay > = 0 ) {
wait_ms ( 1 ) ;
}
else {
for ( int8_t r = MATRIX_ROWS - 1 ; r > = 0 ; - - r ) {
matrix [ r ] = debouncing_matrix [ r ] ;
for ( uint8_t i = 0 ; i < MATRIX_ROWS ; i + + ) {
select_row ( i ) ;
wait_us ( 30 ) ; // without this wait read unstable value.
matrix_row_t cols = read_cols ( ) ;
if ( matrix_debouncing [ i ] ! = cols ) {
matrix_debouncing [ i ] = cols ;
if ( debouncing ) {
debug ( " bounce!: " ) ; debug_hex ( debouncing ) ; debug ( " \n " ) ;
}
debouncing = DEBOUNCING_DELAY ;
}
unselect_rows ( ) ;
}
matrix_scan_quantum ( ) ;
return 1 ;
}
static void toggle_row ( uint8_t row ) {
/* PINxn */
_SFR_IO8 ( ( row_pins [ row ] > > 4 ) ) = _BV ( row_pins [ row ] & 0xF ) ;
}
static matrix_row_t read_cols ( void ) {
matrix_row_t state = 0 ;
for ( int8_t c = MATRIX_COLS - 1 ; c > = 0 ; - - c ) {
/* PINxn */
if ( ! ( _SFR_IO8 ( ( col_pins [ c ] > > 4 ) ) & _BV ( col_pins [ c ] & 0xF ) ) ) {
state | = ( matrix_row_t ) 1 < < c ;
if ( debouncing ) {
if ( - - debouncing ) {
wait_us ( 1 ) ;
} else {
for ( uint8_t i = 0 ; i < MATRIX_ROWS ; i + + ) {
matrix [ i ] = matrix_debouncing [ i ] ;
}
}
}
return state ;
}
matrix_row_t matrix_get_row ( uint8_t row ) {
return matrix [ row ] ;
}
# else
uint8_t matrix_scan ( void ) {
static matrix_col_t debouncing_matrix [ MATRIX_COLS ] ;
for ( int8_t c = MATRIX_COLS - 1 ; c > = 0 ; - - c ) {
toggle_col ( c ) ;
matrix_col_t state = read_rows ( ) ;
if ( debouncing_matrix [ c ] ! = state ) {
debouncing_matrix [ c ] = state ;
debouncing_delay = DEBOUNCING_DELAY ;
for ( uint8_t i = 0 ; i < MATRIX_COLS ; i + + ) {
select_row ( i ) ;
wait_us ( 30 ) ; // without this wait read unstable value.
matrix_row_t rows = read_cols ( ) ;
if ( matrix_reversed_debouncing [ i ] ! = rows ) {
matrix_reversed_debouncing [ i ] = rows ;
if ( debouncing ) {
debug ( " bounce!: " ) ; debug_hex ( debouncing ) ; debug ( " \n " ) ;
}
debouncing = DEBOUNCING_DELAY ;
}
toggle_col ( c ) ;
unselect_rows( ) ;
}
if ( debouncing_delay > = 0 ) {
dprintf ( " Debouncing delay remaining: %X \n " , debouncing_delay ) ;
- - debouncing_delay ;
if ( debouncing_delay > = 0 ) {
wait_ms ( 1 ) ;
}
else {
for ( int8_t c = MATRIX_COLS - 1 ; c > = 0 ; - - c ) {
matrix [ c ] = debouncing_matrix [ c ] ;
if ( debouncing ) {
if ( - - debouncing ) {
wait_us ( 1 ) ;
} else {
for ( uint8_t i = 0 ; i < MATRIX_COLS ; i + + ) {
matrix_reversed [ i ] = matrix_reversed_debouncing [ i ] ;
}
}
}
for ( uint8_t y = 0 ; y < MATRIX_ROWS ; y + + ) {
matrix_row_t row = 0 ;
for ( uint8_t x = 0 ; x < MATRIX_COLS ; x + + ) {
row | = ( ( matrix_reversed [ x ] & ( 1 < < y ) ) > > y ) < < x ;
}
matrix [ y ] = row ;
}
# endif
matrix_scan_quantum ( ) ;
return 1 ;
}
static void toggle_col ( uint8_t col ) {
/* PINxn */
_SFR_IO8 ( ( col_pins [ col ] > > 4 ) ) = _BV ( col_pins [ col ] & 0xF ) ;
bool matrix_is_modified ( void )
{
if ( debouncing ) return false ;
return true ;
}
static matrix_col_t read_rows ( void ) {
matrix_col_t state = 0 ;
for ( int8_t r = MATRIX_ROWS - 1 ; r > = 0 ; - - r ) {
/* PINxn */
if ( ! ( _SFR_IO8 ( ( row_pins [ r ] > > 4 ) ) & _BV ( row_pins [ r ] & 0xF ) ) ) {
state | = ( matrix_col_t ) 1 < < r ;
}
inline
bool matrix_is_on ( uint8_t row , uint8_t col )
{
return ( matrix [ row ] & ( ( matrix_row_t ) 1 < col ) ) ;
}
inline
matrix_row_t matrix_get_row ( uint8_t row )
{
return matrix [ row ] ;
}
void matrix_print ( void )
{
print ( " \n r/c 0123456789ABCDEF \n " ) ;
for ( uint8_t row = 0 ; row < MATRIX_ROWS ; row + + ) {
phex ( row ) ; print ( " : " ) ;
pbin_reverse16 ( matrix_get_row ( row ) ) ;
print ( " \n " ) ;
}
return state ;
}
matrix_row_t matrix_get_row ( uint8_t row ) {
matrix_row_t state = 0 ;
matrix_col_t mask = ( matrix_col_t ) 1 < < row ;
for ( int8_t c = MATRIX_COLS - 1 ; c > = 0 ; - - c ) {
if ( matrix [ c ] & mask ) {
state | = ( matrix_row_t ) 1 < < c ;
}
uint8_t matrix_key_count ( void )
{
uint8_t count = 0 ;
for ( uint8_t i = 0 ; i < MATRIX_ROWS ; i + + ) {
count + = bitpop16 ( matrix [ i ] ) ;
}
return state ;
return count ;
}
static void init_cols ( void )
{
# if DIODE_DIRECTION == COL2ROW
for ( int x = 0 ; x < MATRIX_COLS ; x + + ) {
int pin = col_pins [ x ] ;
# else
for ( int x = 0 ; x < MATRIX_ROWS ; x + + ) {
int pin = row_pins [ x ] ;
# endif
bool matrix_is_modified ( void ) {
if ( debouncing_delay > = 0 ) return false ;
return true ;
_SFR_IO8 ( ( pin > > 4 ) + 1 ) & = ~ _BV ( pin & 0xF ) ;
_SFR_IO8 ( ( pin > > 4 ) + 2 ) | = _BV ( pin & 0xF ) ;
}
}
bool matrix_is_on ( uint8_t row , uint8_t col ) {
return matrix_get_row ( row ) & ( matrix_row_t ) 1 < < col ;
}
static matrix_row_t read_cols ( void )
{
matrix_row_t result = 0 ;
void matrix_print ( void ) {
dprintln ( " Human-readable matrix state: " ) ;
for ( uint8_t r = 0 ; r < MATRIX_ROWS ; r + + ) {
dprintf ( " State of row %X: %016b \n " , r , bitrev16 ( matrix_get_row ( r ) ) ) ;
# if DIODE_DIRECTION == COL2ROW
for ( int x = 0 ; x < MATRIX_COLS ; x + + ) {
int pin = col_pins [ x ] ;
# else
for ( int x = 0 ; x < MATRIX_ROWS ; x + + ) {
int pin = row_pins [ x ] ;
# endif
result | = ( _SFR_IO8 ( pin > > 4 ) & _BV ( pin & 0xF ) ) ? 0 : ( SHIFTER < < x ) ;
}
return result ;
}
uint8_t matrix_key_count ( void ) {
uint8_t count = 0 ;
for ( int8_t r = MATRIX_ROWS - 1 ; r > = 0 ; - - r ) {
count + = bitpop16 ( matrix_get_row ( r ) ) ;
static void unselect_rows ( void )
{
# if DIODE_DIRECTION == COL2ROW
for ( int x = 0 ; x < MATRIX_ROWS ; x + + ) {
int pin = row_pins [ x ] ;
# else
for ( int x = 0 ; x < MATRIX_COLS ; x + + ) {
int pin = col_pins [ x ] ;
# endif
_SFR_IO8 ( ( pin > > 4 ) + 1 ) & = ~ _BV ( pin & 0xF ) ;
_SFR_IO8 ( ( pin > > 4 ) + 2 ) | = _BV ( pin & 0xF ) ;
}
return count ;
}
static void select_row ( uint8_t row )
{
# if DIODE_DIRECTION == COL2ROW
int pin = row_pins [ row ] ;
# else
int pin = col_pins [ row ] ;
# endif
_SFR_IO8 ( ( pin > > 4 ) + 1 ) | = _BV ( pin & 0xF ) ;
_SFR_IO8 ( ( pin > > 4 ) + 2 ) & = ~ _BV ( pin & 0xF ) ;
}