@ -21,9 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
# include <stdint.h>
# include <stdbool.h>
# include <avr/io.h>
# include <avr/wdt.h>
# include <avr/interrupt.h>
# include <util/delay.h>
# include "wait.h"
# include "print.h"
# include "debug.h"
# include "util.h"
@ -31,6 +29,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
# include "split_util.h"
# include "pro_micro.h"
# include "config.h"
# include "timer.h"
# ifdef USE_I2C
# include "i2c.h"
@ -38,14 +37,29 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
# include "serial.h"
# endif
# ifndef DEBOUNC E
# define DEBOUNCE 5
# ifndef DEBOUNC ING_D ELAY
# define DEBOUNCING_DELAY 5
# endif
# if (DEBOUNCING_DELAY > 0)
static uint16_t debouncing_time ;
static bool debouncing = false ;
# endif
# if (MATRIX_COLS <= 8)
# define print_matrix_header() print("\nr / c 01234567\n")
# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
# define matrix_bitpop(i) bitpop(matrix[i])
# define ROW_SHIFTER ((uint8_t)1)
# else
# error "Currently only supports 8 COLS"
# endif
static matrix_row_t matrix_debouncing [ MATRIX_ROWS ] ;
# define ERROR_DISCONNECT_COUNT 5
static uint8_t debouncing = DEBOUNCE ;
static const int ROWS_PER_HAND = MATRIX_ROWS / 2 ;
# define ROWS_PER_HAND (MATRIX_ROWS / 2)
static uint8_t error_count = 0 ;
static const uint8_t row_pins [ MATRIX_ROWS ] = MATRIX_ROW_PINS ;
@ -55,11 +69,19 @@ static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
static matrix_row_t matrix [ MATRIX_ROWS ] ;
static matrix_row_t matrix_debouncing [ MATRIX_ROWS ] ;
static matrix_row_t read_cols ( void ) ;
static void init_cols ( void ) ;
static void unselect_rows ( void ) ;
static void select_row ( uint8_t row ) ;
# if (DIODE_DIRECTION == COL2ROW)
static void init_cols ( void ) ;
static bool read_cols_on_row ( matrix_row_t current_matrix [ ] , uint8_t current_row ) ;
static void unselect_rows ( void ) ;
static void select_row ( uint8_t row ) ;
static void unselect_row ( uint8_t row ) ;
# elif (DIODE_DIRECTION == ROW2COL)
static void init_rows ( void ) ;
static bool read_rows_on_col ( matrix_row_t current_matrix [ ] , uint8_t current_col ) ;
static void unselect_cols ( void ) ;
static void unselect_col ( uint8_t col ) ;
static void select_col ( uint8_t col ) ;
# endif
__attribute__ ( ( weak ) )
void matrix_init_quantum ( void ) {
matrix_init_kb ( ) ;
@ -118,33 +140,54 @@ void matrix_init(void)
}
matrix_init_quantum ( ) ;
}
uint8_t _matrix_scan ( void )
{
// Right hand is stored after the left in the matirx so, we need to offset it
int offset = isLeftHand ? 0 : ( ROWS_PER_HAND ) ;
# if (DIODE_DIRECTION == COL2ROW)
// Set row, read cols
for ( uint8_t current_row = 0 ; current_row < ROWS_PER_HAND ; current_row + + ) {
# if (DEBOUNCING_DELAY > 0)
bool matrix_changed = read_cols_on_row ( matrix_debouncing + offset , current_row ) ;
if ( matrix_changed ) {
debouncing = true ;
debouncing_time = timer_read ( ) ;
PORTD ^ = ( 1 < < 2 ) ;
}
# else
read_cols_on_row ( matrix + offset , current_row ) ;
# endif
}
# elif (DIODE_DIRECTION == ROW2COL)
// Set col, read rows
for ( uint8_t current_col = 0 ; current_col < MATRIX_COLS ; current_col + + ) {
# if (DEBOUNCING_DELAY > 0)
bool matrix_changed = read_rows_on_col ( matrix_debouncing + offset , current_col ) ;
if ( matrix_changed ) {
debouncing = true ;
debouncing_time = timer_read ( ) ;
}
# else
read_rows_on_col ( matrix + offset , current_col ) ;
# endif
for ( uint8_t i = 0 ; i < ROWS_PER_HAND ; i + + ) {
select_row ( i ) ;
_delay_us ( 30 ) ; // without this wait read unstable value.
matrix_row_t cols = read_cols ( ) ;
if ( matrix_debouncing [ i + offset ] ! = cols ) {
matrix_debouncing [ i + offset ] = cols ;
debouncing = DEBOUNCE ;
}
unselect_rows ( ) ;
}
# endif
if ( debouncing ) {
if ( - - debouncing ) {
_delay_ms ( 1 ) ;
} else {
# if (DEBOUNCING_DELAY > 0)
if ( debouncing & & ( timer_elapsed ( debouncing_time ) > DEBOUNCING_DELAY ) ) {
for ( uint8_t i = 0 ; i < ROWS_PER_HAND ; i + + ) {
matrix [ i + offset ] = matrix_debouncing [ i + offset ] ;
}
debouncing = false ;
}
}
# endif
return 1 ;
}
@ -200,9 +243,7 @@ int serial_transaction(void) {
uint8_t matrix_scan ( void )
{
int ret = _matrix_scan ( ) ;
uint8_t ret = _matrix_scan ( ) ;
# ifdef USE_I2C
if ( i2c_transaction ( ) ) {
@ -233,11 +274,10 @@ uint8_t matrix_scan(void)
void matrix_slave_scan ( void ) {
_matrix_scan ( ) ;
int offset = ( isLeftHand ) ? 0 : ( MATRIX_ROWS / 2 ) ;
int offset = ( isLeftHand ) ? 0 : ROWS_PER_HAND ;
# ifdef USE_I2C
for ( int i = 0 ; i < ROWS_PER_HAND ; + + i ) {
/* i2c_slave_buffer[i] = matrix[offset+i]; */
i2c_slave_buffer [ i ] = matrix [ offset + i ] ;
}
# else // USE_SERIAL
@ -284,33 +324,141 @@ uint8_t matrix_key_count(void)
return count ;
}
static void init_cols ( void )
# if (DIODE_DIRECTION == COL2ROW)
static void init_cols ( void )
{
for ( int x = 0 ; x < MATRIX_COLS ; x + + ) {
_SFR_IO8 ( ( col_pins [ x ] > > 4 ) + 1 ) & = ~ _BV ( col_pins [ x ] & 0xF ) ;
_SFR_IO8 ( ( col_pins [ x ] > > 4 ) + 2 ) | = _BV ( col_pins [ x ] & 0xF ) ;
for ( uint8_t x = 0 ; x < MATRIX_COLS ; x + + ) {
uint8_t pin = col_pins [ x ] ;
_SFR_IO8 ( ( pin > > 4 ) + 1 ) & = ~ _BV ( pin & 0xF ) ; // IN
_SFR_IO8 ( ( pin > > 4 ) + 2 ) | = _BV ( pin & 0xF ) ; // HI
}
}
static matrix_row_t read_cols ( void )
static bool read_cols_on_row ( matrix_row_t current_matrix [ ] , uint8_t current_row )
{
matrix_row_t result = 0 ;
for ( int x = 0 ; x < MATRIX_COLS ; x + + ) {
result | = ( _SFR_IO8 ( col_pins [ x ] > > 4 ) & _BV ( col_pins [ x ] & 0xF ) ) ? 0 : ( 1 < < x ) ;
// Store last value of row prior to reading
matrix_row_t last_row_value = current_matrix [ current_row ] ;
// Clear data in matrix row
current_matrix [ current_row ] = 0 ;
// Select row and wait for row selecton to stabilize
select_row ( current_row ) ;
wait_us ( 30 ) ;
// For each col...
for ( uint8_t col_index = 0 ; col_index < MATRIX_COLS ; col_index + + ) {
// Select the col pin to read (active low)
uint8_t pin = col_pins [ col_index ] ;
uint8_t pin_state = ( _SFR_IO8 ( pin > > 4 ) & _BV ( pin & 0xF ) ) ;
// Populate the matrix row with the state of the col pin
current_matrix [ current_row ] | = pin_state ? 0 : ( ROW_SHIFTER < < col_index ) ;
}
return result ;
// Unselect row
unselect_row ( current_row ) ;
return ( last_row_value ! = current_matrix [ current_row ] ) ;
}
static void select_row ( uint8_t row )
{
uint8_t pin = row_pins [ row ] ;
_SFR_IO8 ( ( pin > > 4 ) + 1 ) | = _BV ( pin & 0xF ) ; // OUT
_SFR_IO8 ( ( pin > > 4 ) + 2 ) & = ~ _BV ( pin & 0xF ) ; // LOW
}
static void unselect_row ( uint8_t row )
{
uint8_t pin = row_pins [ row ] ;
_SFR_IO8 ( ( pin > > 4 ) + 1 ) & = ~ _BV ( pin & 0xF ) ; // IN
_SFR_IO8 ( ( pin > > 4 ) + 2 ) | = _BV ( pin & 0xF ) ; // HI
}
static void unselect_rows ( void )
{
for ( int x = 0 ; x < ROWS_PER_HAND ; x + + ) {
_SFR_IO8 ( ( row_pins [ x ] > > 4 ) + 1 ) & = ~ _BV ( row_pins [ x ] & 0xF ) ;
_SFR_IO8 ( ( row_pins [ x ] > > 4 ) + 2 ) | = _BV ( row_pins [ x ] & 0xF ) ;
for ( uint8_t x = 0 ; x < ROWS_PER_HAND ; x + + ) {
uint8_t pin = row_pins [ x ] ;
_SFR_IO8 ( ( pin > > 4 ) + 1 ) & = ~ _BV ( pin & 0xF ) ; // IN
_SFR_IO8 ( ( pin > > 4 ) + 2 ) | = _BV ( pin & 0xF ) ; // HI
}
}
static void select_row ( uint8_t row )
# elif (DIODE_DIRECTION == ROW2COL)
static void init_rows ( void )
{
for ( uint8_t x = 0 ; x < ROWS_PER_HAND ; x + + ) {
uint8_t pin = row_pins [ x ] ;
_SFR_IO8 ( ( pin > > 4 ) + 1 ) & = ~ _BV ( pin & 0xF ) ; // IN
_SFR_IO8 ( ( pin > > 4 ) + 2 ) | = _BV ( pin & 0xF ) ; // HI
}
}
static bool read_rows_on_col ( matrix_row_t current_matrix [ ] , uint8_t current_col )
{
bool matrix_changed = false ;
// Select col and wait for col selecton to stabilize
select_col ( current_col ) ;
wait_us ( 30 ) ;
// For each row...
for ( uint8_t row_index = 0 ; row_index < ROWS_PER_HAND ; row_index + + )
{
// Store last value of row prior to reading
matrix_row_t last_row_value = current_matrix [ row_index ] ;
// Check row pin state
if ( ( _SFR_IO8 ( row_pins [ row_index ] > > 4 ) & _BV ( row_pins [ row_index ] & 0xF ) ) = = 0 )
{
// Pin LO, set col bit
current_matrix [ row_index ] | = ( ROW_SHIFTER < < current_col ) ;
}
else
{
// Pin HI, clear col bit
current_matrix [ row_index ] & = ~ ( ROW_SHIFTER < < current_col ) ;
}
// Determine if the matrix changed state
if ( ( last_row_value ! = current_matrix [ row_index ] ) & & ! ( matrix_changed ) )
{
matrix_changed = true ;
}
}
// Unselect col
unselect_col ( current_col ) ;
return matrix_changed ;
}
static void select_col ( uint8_t col )
{
uint8_t pin = col_pins [ col ] ;
_SFR_IO8 ( ( pin > > 4 ) + 1 ) | = _BV ( pin & 0xF ) ; // OUT
_SFR_IO8 ( ( pin > > 4 ) + 2 ) & = ~ _BV ( pin & 0xF ) ; // LOW
}
static void unselect_col ( uint8_t col )
{
uint8_t pin = col_pins [ col ] ;
_SFR_IO8 ( ( pin > > 4 ) + 1 ) & = ~ _BV ( pin & 0xF ) ; // IN
_SFR_IO8 ( ( pin > > 4 ) + 2 ) | = _BV ( pin & 0xF ) ; // HI
}
static void unselect_cols ( void )
{
_SFR_IO8 ( ( row_pins [ row ] > > 4 ) + 1 ) | = _BV ( row_pins [ row ] & 0xF ) ;
_SFR_IO8 ( ( row_pins [ row ] > > 4 ) + 2 ) & = ~ _BV ( row_pins [ row ] & 0xF ) ;
for ( uint8_t x = 0 ; x < MATRIX_COLS ; x + + ) {
uint8_t pin = col_pins [ x ] ;
_SFR_IO8 ( ( pin > > 4 ) + 1 ) & = ~ _BV ( pin & 0xF ) ; // IN
_SFR_IO8 ( ( pin > > 4 ) + 2 ) | = _BV ( pin & 0xF ) ; // HI
}
}
# endif