// ISR dla Timer0: Obsługuje skanowanie klawiatury (Wersja PRO z pełną ochroną)
SI_INTERRUPT(TIMER0_ISR, TIMER0_IRQn)
{
char old_SFRPAGE = SFRPAGE;
// Tablica przechowująca stan całej klawiatury (4 wiersze)
static unsigned char matrix_state[4] = {0x0F, 0x0F, 0x0F, 0x0F};
SFRPAGE = LEGACY_PAGE;
// Przeładowanie wartości licznika Timer0
TH0 = (char)((65535-5000)>>8);
TL0 = (char)((65535-5000)>>0);
SFRPAGE = CONFIG_PAGE;
// 1. ODCZYT: Zapisujemy stan wiersza (który ustabilizował się od poprzedniego przerwania)
matrix_state[keyboard_counter] = P4 & 0x0F;
// 2. PRZEJŚCIE do kolejnego wiersza
keyboard_counter++;
// 3. ANALIZA MATRYCY: Jeśli przeskanowaliśmy wszystkie 4 wiersze
if (keyboard_counter >= 4)
{
unsigned char keys_pressed = 0; // Licznik wciśniętych klawiszy
unsigned char active_r = 0;
unsigned char active_c = 0;
char r;
keyboard_counter = 0; // Reset licznika dla następnego cyklu
// Zliczamy dokładnie, ile klawiszy jest wciśniętych w całej matrycy
for (r = 0; r < 4; r++) {
if ((matrix_state[r] & 0x01) == 0) { keys_pressed++; active_r = r; active_c = 0; }
if ((matrix_state[r] & 0x02) == 0) { keys_pressed++; active_r = r; active_c = 1; }
if ((matrix_state[r] & 0x04) == 0) { keys_pressed++; active_r = r; active_c = 2; }
if ((matrix_state[r] & 0x08) == 0) { keys_pressed++; active_r = r; active_c = 3; }
}
// 4. WYNIK: Zgodnie z instrukcją - ignorujemy wielokrotne wciśnięcia
if (keys_pressed == 1) {
// DOKŁADNIE jeden klawisz wciśnięty - wyświetl go
led_display[0] = key_codes[active_r][active_c];
} else {
// Żaden klawisz lub więcej niż jeden (błąd) - wygaś ekran
led_display[0] = 0x00;
}
}
// 5. PRZYGOTOWANIE sprzętu dla następnego przerwania
// Ustawienie '0' na wybranej linii wyboru (P4.4 - P4.7)
// Odczyt tego stanu nastąpi dopiero za kilka ms przy kolejnym wejściu do ISR!
P4 = ~(1 << (keyboard_counter + 4)) | 0x0F;
SFRPAGE = old_SFRPAGE;
return;
}