@ -33,14 +33,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
# include "debug.h"
# include "debug.h"
# include "util.h"
# include "util.h"
# include "matrix.h"
# include "matrix.h"
# include "debounce.h"
# include QMK_KEYBOARD_H
# include QMK_KEYBOARD_H
# ifdef DEBUG_MATRIX_SCAN_RATE
# ifdef DEBUG_MATRIX_SCAN_RATE
# include "timer.h"
# include "timer.h"
# endif
# endif
/*
/*
* This constant define not debouncing time in msecs , but amount of matrix
* This constant define not debouncing time in msecs , assuming eager_pr .
* scan loops which should be made to get stable debounced results .
*
*
* On Ergodox matrix scan rate is relatively low , because of slow I2C .
* 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 .
* Now it ' s only 317 scans / second , or about 3.15 msec / scan .
@ -56,17 +56,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
# endif
# endif
/* matrix state(1:on, 0:off) */
/* matrix state(1:on, 0:off) */
static matrix_row_t matrix [ MATRIX_ROWS ] ;
static matrix_row_t raw_matrix [ MATRIX_ROWS ] ; // raw values
/*
static matrix_row_t matrix [ MATRIX_ROWS ] ; // debounced values
* matrix state ( 1 : on , 0 : off )
* contains the raw values without debounce filtering of the last read cycle .
*/
static matrix_row_t raw_matrix [ MATRIX_ROWS ] ;
// Debouncing: store for each key the number of scans until it's eligible to
// change. When scanning the matrix, ignore any changes in keys that have
// already changed in the last DEBOUNCE scans.
static uint8_t debounce_matrix [ MATRIX_ROWS * MATRIX_COLS ] ;
static matrix_row_t read_cols ( uint8_t row ) ;
static matrix_row_t read_cols ( uint8_t row ) ;
static void init_cols ( void ) ;
static void init_cols ( void ) ;
@ -81,61 +72,38 @@ uint32_t matrix_timer;
uint32_t matrix_scan_count ;
uint32_t matrix_scan_count ;
# endif
# endif
__attribute__ ( ( weak ) ) void matrix_init_user ( void ) { }
__attribute__ ( ( weak ) )
__attribute__ ( ( weak ) ) void matrix_scan_user ( void ) { }
void matrix_init_user ( void ) { }
__attribute__ ( ( weak ) )
__attribute__ ( ( weak ) ) void matrix_init_kb ( void ) { matrix_init_user ( ) ; }
void matrix_scan_user ( void ) { }
__attribute__ ( ( weak ) )
void matrix_init_kb ( void ) {
matrix_init_user ( ) ;
}
__attribute__ ( ( weak ) )
__attribute__ ( ( weak ) ) void matrix_scan_kb ( void ) { matrix_scan_user ( ) ; }
void matrix_scan_kb ( void ) {
matrix_scan_user ( ) ;
}
inline
inline uint8_t matrix_rows ( void ) { return MATRIX_ROWS ; }
uint8_t matrix_rows ( void )
{
return MATRIX_ROWS ;
}
inline
inline uint8_t matrix_cols ( void ) { return MATRIX_COLS ; }
uint8_t matrix_cols ( void )
{
return MATRIX_COLS ;
}
void matrix_init ( void )
void matrix_init ( void ) {
{
// initialize row and col
// initialize row and col
mcp23018_status = init_mcp23018 ( ) ;
mcp23018_status = init_mcp23018 ( ) ;
unselect_rows ( ) ;
unselect_rows ( ) ;
init_cols ( ) ;
init_cols ( ) ;
// initialize matrix state: all keys off
// initialize matrix state: all keys off
for ( uint8_t i = 0 ; i < MATRIX_ROWS ; i + + ) {
for ( uint8_t i = 0 ; i < MATRIX_ROWS ; i + + ) {
matrix [ i ] = 0 ;
matrix [ i ] = 0 ;
raw_matrix [ i ] = 0 ;
raw_matrix [ i ] = 0 ;
for ( uint8_t j = 0 ; j < MATRIX_COLS ; + + j ) {
debounce_matrix [ i * MATRIX_COLS + j ] = 0 ;
}
}
}
# ifdef DEBUG_MATRIX_SCAN_RATE
# ifdef DEBUG_MATRIX_SCAN_RATE
matrix_timer = timer_read32 ( ) ;
matrix_timer = timer_read32 ( ) ;
matrix_scan_count = 0 ;
matrix_scan_count = 0 ;
# endif
# endif
debounce_init ( MATRIX_ROWS ) ;
matrix_init_quantum ( ) ;
matrix_init_quantum ( ) ;
}
}
void matrix_power_up ( void ) {
void matrix_power_up ( void ) {
@ -145,7 +113,7 @@ void matrix_power_up(void) {
init_cols ( ) ;
init_cols ( ) ;
// initialize matrix state: all keys off
// initialize matrix state: all keys off
for ( uint8_t i = 0 ; i < MATRIX_ROWS ; i + + ) {
for ( uint8_t i = 0 ; i < MATRIX_ROWS ; i + + ) {
matrix [ i ] = 0 ;
matrix [ i ] = 0 ;
}
}
@ -155,36 +123,7 @@ void matrix_power_up(void) {
# endif
# endif
}
}
// Returns a matrix_row_t whose bits are set if the corresponding key should be
uint8_t matrix_scan ( void ) {
// eligible to change in this scan.
matrix_row_t debounce_mask ( matrix_row_t rawcols , uint8_t row ) {
matrix_row_t result = 0 ;
matrix_row_t change = rawcols ^ raw_matrix [ row ] ;
raw_matrix [ row ] = rawcols ;
for ( uint8_t i = 0 ; i < MATRIX_COLS ; + + i ) {
if ( debounce_matrix [ row * MATRIX_COLS + i ] ) {
- - debounce_matrix [ row * MATRIX_COLS + i ] ;
} else {
result | = ( 1 < < i ) ;
}
if ( change & ( 1 < < i ) ) {
debounce_matrix [ row * MATRIX_COLS + i ] = DEBOUNCE ;
}
}
return result ;
}
matrix_row_t debounce_read_cols ( uint8_t row ) {
// Read the row without debouncing filtering and store it for later usage.
matrix_row_t cols = read_cols ( row ) ;
// Get the Debounce mask.
matrix_row_t mask = debounce_mask ( cols , row ) ;
// debounce the row and return the result.
return ( cols & mask ) | ( matrix [ row ] & ~ mask ) ; ;
}
uint8_t matrix_scan ( void )
{
if ( mcp23018_status ) { // if there was an error
if ( mcp23018_status ) { // if there was an error
if ( + + mcp23018_reset_loop = = 0 ) {
if ( + + mcp23018_reset_loop = = 0 ) {
// if (++mcp23018_reset_loop >= 1300) {
// if (++mcp23018_reset_loop >= 1300) {
@ -205,7 +144,7 @@ uint8_t matrix_scan(void)
matrix_scan_count + + ;
matrix_scan_count + + ;
uint32_t timer_now = timer_read32 ( ) ;
uint32_t timer_now = timer_read32 ( ) ;
if ( TIMER_DIFF_32 ( timer_now , matrix_timer ) > 1000 ) {
if ( TIMER_DIFF_32 ( timer_now , matrix_timer ) > 1000 ) {
print ( " matrix scan frequency: " ) ;
print ( " matrix scan frequency: " ) ;
pdec ( matrix_scan_count ) ;
pdec ( matrix_scan_count ) ;
print ( " \n " ) ;
print ( " \n " ) ;
@ -219,20 +158,21 @@ uint8_t matrix_scan(void)
mcp23018_status = ergodox_left_leds_update ( ) ;
mcp23018_status = ergodox_left_leds_update ( ) ;
# endif // LEFT_LEDS
# endif // LEFT_LEDS
for ( uint8_t i = 0 ; i < MATRIX_ROWS_PER_SIDE ; i + + ) {
for ( uint8_t i = 0 ; i < MATRIX_ROWS_PER_SIDE ; i + + ) {
// select rows from left and right hands
select_row ( i ) ;
select_row ( i ) ;
// and select on left hand
select_row ( i + MATRIX_ROWS_PER_SIDE ) ;
select_row ( i + MATRIX_ROWS_PER_SIDE ) ;
// we don't need a 30us delay anymore, because selecting a
// we don't need a 30us delay anymore, because selecting a
// left-hand row requires more than 30us for i2c.
// left-hand row requires more than 30us for i2c.
// grab cols from left hand
// grab left + right cols.
matrix [ i ] = debounce_read_cols ( i ) ;
raw_matrix [ i ] = read_cols ( i ) ;
// grab cols from right hand
raw_matrix [ i + MATRIX_ROWS_PER_SIDE ] = read_cols ( i + MATRIX_ROWS_PER_SIDE ) ;
matrix [ i + MATRIX_ROWS_PER_SIDE ] = debounce_read_cols ( i + MATRIX_ROWS_PER_SIDE ) ;
unselect_rows ( ) ;
unselect_rows ( ) ;
}
}
debounce ( raw_matrix , matrix , MATRIX_ROWS , true ) ;
matrix_scan_quantum ( ) ;
matrix_scan_quantum ( ) ;
return 1 ;
return 1 ;
@ -243,30 +183,21 @@ bool matrix_is_modified(void) // deprecated and evidently not called.
return true ;
return true ;
}
}
inline
inline bool matrix_is_on ( uint8_t row , uint8_t col ) { return ( matrix [ row ] & ( ( matrix_row_t ) 1 < < col ) ) ; }
bool matrix_is_on ( uint8_t row , uint8_t col )
{
return ( matrix [ row ] & ( ( matrix_row_t ) 1 < < col ) ) ;
}
inline
inline matrix_row_t matrix_get_row ( uint8_t row ) { return matrix [ row ] ; }
matrix_row_t matrix_get_row ( uint8_t row )
{
return matrix [ row ] ;
}
void matrix_print ( void )
void matrix_print ( void ) {
{
print ( " \n r/c 0123456789ABCDEF \n " ) ;
print ( " \n r/c 0123456789ABCDEF \n " ) ;
for ( uint8_t row = 0 ; row < MATRIX_ROWS ; row + + ) {
for ( uint8_t row = 0 ; row < MATRIX_ROWS ; row + + ) {
phex ( row ) ; print ( " : " ) ;
phex ( row ) ;
print ( " : " ) ;
pbin_reverse16 ( matrix_get_row ( row ) ) ;
pbin_reverse16 ( matrix_get_row ( row ) ) ;
print ( " \n " ) ;
print ( " \n " ) ;
}
}
}
}
uint8_t matrix_key_count ( void )
uint8_t matrix_key_count ( void ) {
{
uint8_t count = 0 ;
uint8_t count = 0 ;
for ( uint8_t i = 0 ; i < MATRIX_ROWS ; i + + ) {
for ( uint8_t i = 0 ; i < MATRIX_ROWS ; i + + ) {
count + = bitpop16 ( matrix [ i ] ) ;
count + = bitpop16 ( matrix [ i ] ) ;
@ -284,28 +215,30 @@ uint8_t matrix_key_count(void)
* col : 0 1 2 3 4 5
* col : 0 1 2 3 4 5
* pin : B5 B4 B3 B2 B1 B0
* pin : B5 B4 B3 B2 B1 B0
*/
*/
static void init_cols ( void )
static void init_cols ( void ) {
{
// init on mcp23018
// init on mcp23018
// not needed, already done as part of init_mcp23018()
// not needed, already done as part of init_mcp23018()
// init on teensy
// init on teensy
// Input with pull-up(DDR:0, PORT:1)
// Input with pull-up(DDR:0, PORT:1)
DDRF & = ~ ( 1 < < 7 | 1 < < 6 | 1 < < 5 | 1 < < 4 | 1 < < 1 | 1 < < 0 ) ;
DDRF & = ~ ( 1 < < 7 | 1 < < 6 | 1 < < 5 | 1 < < 4 | 1 < < 1 | 1 < < 0 ) ;
PORTF | = ( 1 < < 7 | 1 < < 6 | 1 < < 5 | 1 < < 4 | 1 < < 1 | 1 < < 0 ) ;
PORTF | = ( 1 < < 7 | 1 < < 6 | 1 < < 5 | 1 < < 4 | 1 < < 1 | 1 < < 0 ) ;
}
}
static matrix_row_t read_cols ( uint8_t row )
static matrix_row_t read_cols ( uint8_t row ) {
{
if ( row < 7 ) {
if ( row < 7 ) {
if ( mcp23018_status ) { // if there was an error
if ( mcp23018_status ) { // if there was an error
return 0 ;
return 0 ;
} else {
} else {
uint8_t data = 0 ;
uint8_t data = 0 ;
mcp23018_status = i2c_start ( I2C_ADDR_WRITE , ERGODOX_EZ_I2C_TIMEOUT ) ; if ( mcp23018_status ) goto out ;
mcp23018_status = i2c_start ( I2C_ADDR_WRITE , ERGODOX_EZ_I2C_TIMEOUT ) ;
mcp23018_status = i2c_write ( GPIOB , ERGODOX_EZ_I2C_TIMEOUT ) ; if ( mcp23018_status ) goto out ;
if ( mcp23018_status ) goto out ;
mcp23018_status = i2c_start ( I2C_ADDR_READ , ERGODOX_EZ_I2C_TIMEOUT ) ; if ( mcp23018_status ) goto out ;
mcp23018_status = i2c_write ( GPIOB , ERGODOX_EZ_I2C_TIMEOUT ) ;
mcp23018_status = i2c_read_nack ( ERGODOX_EZ_I2C_TIMEOUT ) ; if ( mcp23018_status < 0 ) goto out ;
if ( mcp23018_status ) goto out ;
mcp23018_status = i2c_start ( I2C_ADDR_READ , ERGODOX_EZ_I2C_TIMEOUT ) ;
if ( mcp23018_status ) goto out ;
mcp23018_status = i2c_read_nack ( ERGODOX_EZ_I2C_TIMEOUT ) ;
if ( mcp23018_status < 0 ) goto out ;
data = ~ ( ( uint8_t ) mcp23018_status ) ;
data = ~ ( ( uint8_t ) mcp23018_status ) ;
mcp23018_status = I2C_STATUS_SUCCESS ;
mcp23018_status = I2C_STATUS_SUCCESS ;
out :
out :
@ -333,24 +266,22 @@ static matrix_row_t read_cols(uint8_t row)
* row : 0 1 2 3 4 5 6
* row : 0 1 2 3 4 5 6
* pin : A0 A1 A2 A3 A4 A5 A6
* pin : A0 A1 A2 A3 A4 A5 A6
*/
*/
static void unselect_rows ( void )
static void unselect_rows ( void ) {
{
// no need to unselect on mcp23018, because the select step sets all
// no need to unselect on mcp23018, because the select step sets all
// the other row bits high, and it's not changing to a different
// the other row bits high, and it's not changing to a different
// direction
// direction
// unselect on teensy
// unselect on teensy
// Hi-Z(DDR:0, PORT:0) to unselect
// Hi-Z(DDR:0, PORT:0) to unselect
DDRB & = ~ ( 1 < < 0 | 1 < < 1 | 1 < < 2 | 1 < < 3 ) ;
DDRB & = ~ ( 1 < < 0 | 1 < < 1 | 1 < < 2 | 1 < < 3 ) ;
PORTB & = ~ ( 1 < < 0 | 1 < < 1 | 1 < < 2 | 1 < < 3 ) ;
PORTB & = ~ ( 1 < < 0 | 1 < < 1 | 1 < < 2 | 1 < < 3 ) ;
DDRD & = ~ ( 1 < < 2 | 1 < < 3 ) ;
DDRD & = ~ ( 1 < < 2 | 1 < < 3 ) ;
PORTD & = ~ ( 1 < < 2 | 1 < < 3 ) ;
PORTD & = ~ ( 1 < < 2 | 1 < < 3 ) ;
DDRC & = ~ ( 1 < < 6 ) ;
DDRC & = ~ ( 1 < < 6 ) ;
PORTC & = ~ ( 1 < < 6 ) ;
PORTC & = ~ ( 1 < < 6 ) ;
}
}
static void select_row ( uint8_t row )
static void select_row ( uint8_t row ) {
{
if ( row < 7 ) {
if ( row < 7 ) {
// select on mcp23018
// select on mcp23018
if ( mcp23018_status ) { // if there was an error
if ( mcp23018_status ) { // if there was an error
@ -358,9 +289,12 @@ static void select_row(uint8_t row)
} else {
} else {
// set active row low : 0
// set active row low : 0
// set other rows hi-Z : 1
// set other rows hi-Z : 1
mcp23018_status = i2c_start ( I2C_ADDR_WRITE , ERGODOX_EZ_I2C_TIMEOUT ) ; if ( mcp23018_status ) goto out ;
mcp23018_status = i2c_start ( I2C_ADDR_WRITE , ERGODOX_EZ_I2C_TIMEOUT ) ;
mcp23018_status = i2c_write ( GPIOA , ERGODOX_EZ_I2C_TIMEOUT ) ; if ( mcp23018_status ) goto out ;
if ( mcp23018_status ) goto out ;
mcp23018_status = i2c_write ( 0xFF & ~ ( 1 < < row ) , ERGODOX_EZ_I2C_TIMEOUT ) ; if ( mcp23018_status ) goto out ;
mcp23018_status = i2c_write ( GPIOA , ERGODOX_EZ_I2C_TIMEOUT ) ;
if ( mcp23018_status ) goto out ;
mcp23018_status = i2c_write ( 0xFF & ~ ( 1 < < row ) , ERGODOX_EZ_I2C_TIMEOUT ) ;
if ( mcp23018_status ) goto out ;
out :
out :
i2c_stop ( ) ;
i2c_stop ( ) ;
}
}
@ -369,32 +303,32 @@ static void select_row(uint8_t row)
// Output low(DDR:1, PORT:0) to select
// Output low(DDR:1, PORT:0) to select
switch ( row ) {
switch ( row ) {
case 7 :
case 7 :
DDRB | = ( 1 < < 0 ) ;
DDRB | = ( 1 < < 0 ) ;
PORTB & = ~ ( 1 < < 0 ) ;
PORTB & = ~ ( 1 < < 0 ) ;
break ;
break ;
case 8 :
case 8 :
DDRB | = ( 1 < < 1 ) ;
DDRB | = ( 1 < < 1 ) ;
PORTB & = ~ ( 1 < < 1 ) ;
PORTB & = ~ ( 1 < < 1 ) ;
break ;
break ;
case 9 :
case 9 :
DDRB | = ( 1 < < 2 ) ;
DDRB | = ( 1 < < 2 ) ;
PORTB & = ~ ( 1 < < 2 ) ;
PORTB & = ~ ( 1 < < 2 ) ;
break ;
break ;
case 10 :
case 10 :
DDRB | = ( 1 < < 3 ) ;
DDRB | = ( 1 < < 3 ) ;
PORTB & = ~ ( 1 < < 3 ) ;
PORTB & = ~ ( 1 < < 3 ) ;
break ;
break ;
case 11 :
case 11 :
DDRD | = ( 1 < < 2 ) ;
DDRD | = ( 1 < < 2 ) ;
PORTD & = ~ ( 1 < < 2 ) ;
PORTD & = ~ ( 1 < < 2 ) ;
break ;
break ;
case 12 :
case 12 :
DDRD | = ( 1 < < 3 ) ;
DDRD | = ( 1 < < 3 ) ;
PORTD & = ~ ( 1 < < 3 ) ;
PORTD & = ~ ( 1 < < 3 ) ;
break ;
break ;
case 13 :
case 13 :
DDRC | = ( 1 < < 6 ) ;
DDRC | = ( 1 < < 6 ) ;
PORTC & = ~ ( 1 < < 6 ) ;
PORTC & = ~ ( 1 < < 6 ) ;
break ;
break ;
}
}
}
}