Че, правда надо необычное? Вот выдрал, надеюсь, не убил идею и красоту // Коды клавиш: 4x4=16 кодов одиночных нажатий.
// При необходимости добавлять коды (до 4-х нажатий на каждую
// scanLine), изменяя мл.тетраду кода клавиши.
// Длительность дешифрации клавиш при этом не изменится.
#define NO_PRESS ( 0xff )
#define KEY_1 ( 0xee ) /*тетрады: H-scan, L-ret*/
#define KEY_2 ( 0xed )
#define KEY_3 ( 0xeb )
#define KEY_4 ( 0xe7 )
#define KEY_5 ( 0xde )
#define KEY_6 ( 0xdd )
#define KEY_7 ( 0xdb )
#define KEY_8 ( 0xd7 )
#define KEY_9 ( 0xce )
#define KEY_10 ( 0xcd )
#define KEY_11 ( 0xcb )
#define KEY_12 ( 0xc7 )
#define KEY_13 ( 0xbe )
#define KEY_14 ( 0xbd )
#define KEY_15 ( 0xbb )
#define KEY_16 ( 0xb7 )
//-----------------------------------
volatile uint8_t keyData = NO_PRESS; // keyData содержит текущий код
//-----------------------------------
// Обработчик прерывания таймера, например, каждые 5 мс, для опроса матрицы
// Может вызываться и поллингом
void keyHandler( void ) {
static uint16_t stateMsk = (uint16_t)0xffffU; // Маска состояний, где 0 - нажатие
static uint16_t changeFlagsMsk; // Изменения состояний
static uint16_t cnt0, cnt1;
uint16_t sampleMsk; // Конкатенация 4-х RET-тетрад
uint16_t deltaMsk; // Побитовая разница с сэмплов
uint8_t retMsk;
// Сканирование матрицы активным 0 и формирование
// 16-битного значения sampleMsk
scanLine1(); // Активировать 0 на первой линии сканирования
nopNopNop(); // Пауза
retMsk=readRetLines(); // Чтение байта, где мл.тетр.-RET-линии
scanLine2();
sampleMsk = (uint16_t)(retMsk & 0x0f);
retMsk=readRetLines();
scanLine3();
sampleMsk < < = 4; // Сдвиг влево на 4 бита
sampleMsk |= (uint16_t)(retMsk & 0x0f);
retMsk=readRetLines();
scanLine4();
sampleMsk < < = 4; // Сдвиг влево на 4 бита
sampleMsk |= (uint16_t)(retMsk & 0x0f);
retMsk=readRetLines();
scanLineOff(); // Все 8 линий матрицы как pullup-входы.
sampleMsk < < = 4; // Сдвиг влево на 4 бита
sampleMsk |= (uint16_t)(retMsk & 0x0f);
// Антидребезг 4-х проходный.
deltaMsk = (sampleMsk ^ stateMsk);
cnt1 = ((cnt1 ^ cnt0) & deltaMsk);
cnt0 = ((~cnt0) & deltaMsk);
changeFlagsMsk = (deltaMsk & (~(cnt0 | cnt1)));
stateMsk ^= changeFlagsMsk;
// Проверка изменения состояний клавиш
if( !changeFlagsMsk ) {
if( keyData != NO_PRESS ) {
// Здесь возможен счетчик и обработка долгих нажатий,
// например, для выключения или рестарта прибора долгим
// нажатием клавиши (сочетания клавиш)
//.....
}else{
// Здесь возможен счетчик и обработка долгого
// ненажатия клавиш, например, для самоотключения
// батарейного прибора
//.....
}
}else { // Было изменение!
uint8_t u8_tmp;
uint16_t tmpStateMsk;
// Декодирование клавиш
keyData = NO_PRESS;
tmpStateMsk = stateMsk;
u8_tmp = (uint8_t)(tmpStateMsk & 0x0f);
if( u8_tmp != 0x0f ) { keyData=(0xe0 | u8_tmp); }
tmpStateMsk > > = 4; // Сдвиг вправо на 4 бита
u8_tmp = (uint8_t)(tmpStateMsk & 0x0f);
if( u8_tmp != 0x0f ) { keyData=(0xd0 | u8_tmp ); }
tmpStateMsk > > = 4; // Сдвиг вправо на 4 бита
u8_tmp = (uint8_t)(tmpStateMsk & 0x0f);
if( u8_tmp != 0x0f ) { keyData = ( 0xc0 | u8_tmp ); }
tmpStateMsk > > = 4; // Сдвиг вправо на 4 бита
u8_tmp = (uint8_t)(tmpStateMsk & 0x0f);
if( u8_tmp != 0x0f ) { keyData = ( 0xb0 | u8_tmp ); }
}
}
void getKey(void) {
do{ /*keyHandler()*/ ; }while(keyData != NO_PRESS);
do{ /*keyHandler()*/ ; }while(keyData == NO_PRESS);
shortBell();
}
void main(void){
scanLineOff();
keyData=NO_PRESS;
setTimerMs(5);
enable_interrupt();
while(1){
getKey();
//printf
}
}