@ -1,6 +1,6 @@
/*
Copyright 2012 Jun Wako
Generated by planckkeyboard . com ( 2014 Jack Humbert )
Copyright 2014 Jack Humbert
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
@ -15,300 +15,211 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
/*
* scan matrix
*/
# include <stdint.h>
# include <stdbool.h>
# include <avr/io.h>
# include <util/delay.h>
# include "wait.h"
# include "print.h"
# include "debug.h"
# include "util.h"
# include "matrix.h"
# if ndef DEBOUNCE
# define DEBOUNCE 10
# if def MATRIX_HAS_GHOST
# error "The universal matrix.c file cannot be used for this keyboard."
# endif
static uint8_t debouncing = DEBOUNCE ;
/* matrix state(1:on, 0:off) */
static matrix_row_t matrix [ MATRIX_ROWS ] ;
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 ] ;
# ifndef DEBOUNCING_DELAY
# define DEBOUNCING_DELAY 5
# endif
# if MATRIX_COLS > 16
# define SHIFTER 1UL
static const io_pin_t row_pins [ MATRIX_ROWS ] = MATRIX_ROW_PINS ;
static const io_pin_t col_pins [ MATRIX_COLS ] = MATRIX_COL_PINS ;
/* matrix state */
# if DIODE_DIRECTION == COL2ROW
static matrix_row_t matrix [ MATRIX_ROWS ] ;
static matrix_row_t debouncing_matrix [ MATRIX_ROWS ] ;
# else
# define SHIFTER 1
static matrix_col_t matrix [ MATRIX_COLS ] ;
static matrix_col_t debouncing_matrix [ 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 ) ;
static void init_cols ( void ) ;
static void unselect_rows ( void ) ;
static void select_row ( uint8_t row ) ;
# else
static void toggle_col ( uint8_t col ) ;
static matrix_col_t read_rows ( void ) ;
# endif
__attribute__ ( ( weak ) )
void matrix_init_quantum ( void ) {
}
__attribute__ ( ( weak ) )
void matrix_scan_quantum ( void ) {
}
inline
uint8_t matrix_rows ( void )
{
uint8_t matrix_rows ( void ) {
return MATRIX_ROWS ;
}
inline
uint8_t matrix_cols ( void )
{
uint8_t matrix_cols ( void ) {
return MATRIX_COLS ;
}
void matrix_init ( void )
{
// To use PORTF disable JTAG with writing JTD bit twice within four cycles.
MCUCR | = ( 1 < < JTD ) ;
MCUCR | = ( 1 < < JTD ) ;
// 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 ;
}
matrix_init_quantum ( ) ;
}
uint8_t matrix_scan ( void )
{
void matrix_init ( void ) {
/* frees PORTF by setting the JTD bit twice within four cycles */
MCUCR | = _BV ( JTD ) ;
MCUCR | = _BV ( JTD ) ;
/* initializes the I/O pins */
# if DIODE_DIRECTION == COL2ROW
for ( uint8_t i = 0 ; i < MATRIX_ROWS ; i + + ) {
select_row ( i ) ;
_delay_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 = DEBOUNCE ;
}
unselect_rows ( ) ;
}
if ( debouncing ) {
if ( - - debouncing ) {
_delay_ms ( 1 ) ;
} else {
for ( uint8_t i = 0 ; i < MATRIX_ROWS ; i + + ) {
matrix [ i ] = matrix_debouncing [ i ] ;
}
for ( int8_t r = MATRIX_ROWS - 1 ; r > = 0 ; - - r ) {
/* DDRxn */
_SFR_IO8 ( row_pins [ r ] . input_addr + 1 ) | = _BV ( row_pins [ r ] . bit ) ;
toggle_row ( r ) ;
}
for ( int8_t c = MATRIX_COLS - 1 ; c > = 0 ; - - c ) {
/* PORTxn */
_SFR_IO8 ( col_pins [ c ] . input_addr + 2 ) | = _BV ( col_pins [ c ] . bit ) ;
}
# else
for ( uint8_t i = 0 ; i < MATRIX_COLS ; i + + ) {
select_row ( i ) ;
_delay_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 = DEBOUNCE ;
for ( int8_t c = MATRIX_COLS - 1 ; c > = 0 ; - - c ) {
/* DDRxn */
_SFR_IO8 ( col_pins [ c ] . input_addr + 1 ) | = _BV ( col_pins [ c ] . bit ) ;
toggle_col ( c ) ;
}
unselect_rows ( ) ;
for ( int8_t r = MATRIX_ROWS - 1 ; r > = 0 ; - - r ) {
/* PORTxn */
_SFR_IO8 ( row_pins [ r ] . input_addr + 2 ) | = _BV ( row_pins [ r ] . bit ) ;
}
# endif
matrix_init_quantum ( ) ;
}
if ( debouncing ) {
if ( - - debouncing ) {
_delay_ms ( 1 ) ;
} else {
for ( uint8_t i = 0 ; i < MATRIX_COLS ; i + + ) {
matrix_reversed [ i ] = matrix_reversed_debouncing [ i ] ;
# if DIODE_DIRECTION == COL2ROW
uint8_t matrix_scan ( void ) {
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 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 ;
}
bool matrix_is_modified ( void )
{
if ( debouncing ) return false ;
return true ;
static void toggle_row ( uint8_t row ) {
/* PINxn */
_SFR_IO8 ( row_pins [ row ] . input_addr ) = _BV ( row_pins [ row ] . bit ) ;
}
inline
bool matrix_is_on ( uint8_t row , uint8_t col )
{
return ( matrix [ row ] & ( ( matrix_row_t ) 1 < col ) ) ;
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 ] . input_addr ) & _BV ( col_pins [ c ] . bit ) ) ) {
state | = ( matrix_row_t ) 1 < < c ;
}
}
return state ;
}
inline
matrix_row_t matrix_get_row ( uint8_t row )
{
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 " ) ;
# else
uint8_t matrix_scan ( void ) {
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 ;
}
}
uint8_t matrix_key_count ( void )
{
uint8_t count = 0 ;
for ( uint8_t i = 0 ; i < MATRIX_ROWS ; i + + ) {
count + = bitpop16 ( matrix [ i ] ) ;
toggle_col ( c ) ;
}
return count ;
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 ] ;
}
}
}
matrix_scan_quantum ( ) ;
return 1 ;
}
static void init_cols ( void )
{
int B = 0 , C = 0 , D = 0 , E = 0 , F = 0 ;
static void toggle_col ( uint8_t col ) {
/* PINxn */
_SFR_IO8 ( col_pins [ col ] . input_addr ) = _BV ( col_pins [ col ] . bit ) ;
}
# if DIODE_DIRECTION == COL2ROW
for ( int x = 0 ; x < MATRIX_COLS ; x + + ) {
int col = COLS [ x ] ;
# else
for ( int x = 0 ; x < MATRIX_ROWS ; x + + ) {
int col = ROWS [ x ] ;
# endif
if ( ( col & 0xF0 ) = = 0x20 ) {
B | = ( 1 < < ( col & 0x0F ) ) ;
} else if ( ( col & 0xF0 ) = = 0x30 ) {
C | = ( 1 < < ( col & 0x0F ) ) ;
} else if ( ( col & 0xF0 ) = = 0x40 ) {
D | = ( 1 < < ( col & 0x0F ) ) ;
} else if ( ( col & 0xF0 ) = = 0x50 ) {
E | = ( 1 < < ( col & 0x0F ) ) ;
} else if ( ( col & 0xF0 ) = = 0x60 ) {
F | = ( 1 < < ( col & 0x0F ) ) ;
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 ] . input_addr ) & _BV ( row_pins [ r ] . bit ) ) ) {
state | = ( matrix_col_t ) 1 < < r ;
}
}
DDRB & = ~ ( B ) ; PORTB | = ( B ) ;
DDRC & = ~ ( C ) ; PORTC | = ( C ) ;
DDRD & = ~ ( D ) ; PORTD | = ( D ) ;
DDRE & = ~ ( E ) ; PORTE | = ( E ) ;
DDRF & = ~ ( F ) ; PORTF | = ( F ) ;
return state ;
}
static matrix_row_t read_cols ( void )
{
matrix_row_t result = 0 ;
# if DIODE_DIRECTION == COL2ROW
for ( int x = 0 ; x < MATRIX_COLS ; x + + ) {
int col = COLS [ x ] ;
# else
for ( int x = 0 ; x < MATRIX_ROWS ; x + + ) {
int col = ROWS [ x ] ;
# endif
if ( ( col & 0xF0 ) = = 0x20 ) {
result | = ( PINB & ( 1 < < ( col & 0x0F ) ) ? 0 : ( SHIFTER < < x ) ) ;
} else if ( ( col & 0xF0 ) = = 0x30 ) {
result | = ( PINC & ( 1 < < ( col & 0x0F ) ) ? 0 : ( SHIFTER < < x ) ) ;
} else if ( ( col & 0xF0 ) = = 0x40 ) {
result | = ( PIND & ( 1 < < ( col & 0x0F ) ) ? 0 : ( SHIFTER < < x ) ) ;
} else if ( ( col & 0xF0 ) = = 0x50 ) {
result | = ( PINE & ( 1 < < ( col & 0x0F ) ) ? 0 : ( SHIFTER < < x ) ) ;
} else if ( ( col & 0xF0 ) = = 0x60 ) {
result | = ( PINF & ( 1 < < ( col & 0x0F ) ) ? 0 : ( SHIFTER < < x ) ) ;
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 ;
}
}
return result ;
return state ;
}
static void unselect_rows ( void )
{
int B = 0 , C = 0 , D = 0 , E = 0 , F = 0 ;
# if DIODE_DIRECTION == COL2ROW
for ( int x = 0 ; x < MATRIX_ROWS ; x + + ) {
int row = ROWS [ x ] ;
# else
for ( int x = 0 ; x < MATRIX_COLS ; x + + ) {
int row = COLS [ x ] ;
# endif
if ( ( row & 0xF0 ) = = 0x20 ) {
B | = ( 1 < < ( row & 0x0F ) ) ;
} else if ( ( row & 0xF0 ) = = 0x30 ) {
C | = ( 1 < < ( row & 0x0F ) ) ;
} else if ( ( row & 0xF0 ) = = 0x40 ) {
D | = ( 1 < < ( row & 0x0F ) ) ;
} else if ( ( row & 0xF0 ) = = 0x50 ) {
E | = ( 1 < < ( row & 0x0F ) ) ;
} else if ( ( row & 0xF0 ) = = 0x60 ) {
F | = ( 1 < < ( row & 0x0F ) ) ;
}
}
DDRB & = ~ ( B ) ; PORTB | = ( B ) ;
DDRC & = ~ ( C ) ; PORTC | = ( C ) ;
DDRD & = ~ ( D ) ; PORTD | = ( D ) ;
DDRE & = ~ ( E ) ; PORTE | = ( E ) ;
DDRF & = ~ ( F ) ; PORTF | = ( F ) ;
bool matrix_is_modified ( void ) {
if ( debouncing_delay > = 0 ) return false ;
return true ;
}
static void select_row ( uint8_t row )
{
bool matrix_is_on ( uint8_t row , uint8_t col ) {
return matrix_get_row ( row ) & ( matrix_row_t ) 1 < < col ;
}
# if DIODE_DIRECTION == COL2ROW
int row_pin = ROWS [ row ] ;
# else
int row_pin = COLS [ row ] ;
# endif
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 ( ( row_pin & 0xF0 ) = = 0x20 ) {
DDRB | = ( 1 < < ( row_pin & 0x0F ) ) ;
PORTB & = ~ ( 1 < < ( row_pin & 0x0F ) ) ;
} else if ( ( row_pin & 0xF0 ) = = 0x30 ) {
DDRC | = ( 1 < < ( row_pin & 0x0F ) ) ;
PORTC & = ~ ( 1 < < ( row_pin & 0x0F ) ) ;
} else if ( ( row_pin & 0xF0 ) = = 0x40 ) {
DDRD | = ( 1 < < ( row_pin & 0x0F ) ) ;
PORTD & = ~ ( 1 < < ( row_pin & 0x0F ) ) ;
} else if ( ( row_pin & 0xF0 ) = = 0x50 ) {
DDRE | = ( 1 < < ( row_pin & 0x0F ) ) ;
PORTE & = ~ ( 1 < < ( row_pin & 0x0F ) ) ;
} else if ( ( row_pin & 0xF0 ) = = 0x60 ) {
DDRF | = ( 1 < < ( row_pin & 0x0F ) ) ;
PORTF & = ~ ( 1 < < ( row_pin & 0x0F ) ) ;
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 ) ) ;
}
return count ;
}