89 lines
2.5 KiB
C
89 lines
2.5 KiB
C
#include "keyboard.h"
|
||
|
||
char lastKey;
|
||
uint32_t lastScanTime;
|
||
|
||
void initKeyboard(void) {
|
||
// Строки (R1-R4) как выходы с открытым стоком
|
||
// PB7, PB6, PB3, PA10
|
||
GPIOB->MODER = (GPIOB->MODER & ~(3U << (7 * 2))) | (1U << (7 * 2));
|
||
GPIOB->MODER = (GPIOB->MODER & ~(3U << (6 * 2))) | (1U << (6 * 2));
|
||
GPIOB->MODER = (GPIOB->MODER & ~(3U << (3 * 2))) | (1U << (3 * 2));
|
||
GPIOA->MODER = (GPIOA->MODER & ~(3U << (10 * 2))) | (1U << (10 * 2));
|
||
|
||
GPIOB->OTYPER |= (1U << 7) | (1U << 6) | (1U << 3);
|
||
GPIOA->OTYPER |= (1U << 10);
|
||
|
||
// Столбцы (C1-C3) как входы с подтяжкой к питанию
|
||
// PB10, PB4, PB5
|
||
GPIOB->MODER &= ~(3U << (10 * 2) | 3U << (4 * 2) | 3U << (5 * 2));
|
||
GPIOB->PUPDR = (GPIOB->PUPDR & ~(3U << (10 * 2))) | (1U << (10 * 2));
|
||
GPIOB->PUPDR = (GPIOB->PUPDR & ~(3U << (4 * 2))) | (1U << (4 * 2));
|
||
GPIOB->PUPDR = (GPIOB->PUPDR & ~(3U << (5 * 2))) | (1U << (5 * 2));
|
||
|
||
lastKey = '\0';
|
||
lastScanTime = 0;
|
||
}
|
||
|
||
char readKey(void) {
|
||
const uint8_t rows[] = {7, 6, 10, 3}; // R1..R4
|
||
const uint8_t cols[] = {10, 4, 5}; // C1..C3
|
||
|
||
// Только первый ряд задействован: B / D / H
|
||
const char keymap[4][3] = {
|
||
{'B', 'D', 'H'},
|
||
{'?', '?', '?'},
|
||
{'?', '?', '?'},
|
||
{'?', '?', '?'}
|
||
};
|
||
|
||
for (uint8_t i = 0; i < 4; i++) {
|
||
// Активируем текущую строку (тянем в 0)
|
||
if (rows[i] != 10) {
|
||
GPIOB->BSRR = (1U << (rows[i] + 16)); // reset
|
||
} else {
|
||
GPIOA->BSRR = (1U << (rows[i] + 16));
|
||
}
|
||
|
||
// небольшая задержка
|
||
for (volatile int d = 0; d < 100; d++);
|
||
|
||
// Проверяем столбцы
|
||
for (uint8_t j = 0; j < 3; j++) {
|
||
if ((GPIOB->IDR & (1U << cols[j])) == 0) {
|
||
// Деактивируем строку
|
||
if (rows[i] != 10) {
|
||
GPIOB->BSRR = (1U << rows[i]);
|
||
} else {
|
||
GPIOA->BSRR = (1U << rows[i]);
|
||
}
|
||
return keymap[i][j];
|
||
}
|
||
}
|
||
|
||
// Деактивируем строку (отпускаем)
|
||
if (rows[i] != 10) {
|
||
GPIOB->BSRR = (1U << rows[i]);
|
||
} else {
|
||
GPIOA->BSRR = (1U << rows[i]);
|
||
}
|
||
}
|
||
|
||
return '\0';
|
||
}
|
||
|
||
void scanKeyboard(void) {
|
||
// Опрос раз в 100 мс
|
||
if (tickCount - lastScanTime > 100) {
|
||
lastScanTime = tickCount;
|
||
char currentKey = readKey();
|
||
|
||
if (currentKey != '\0' && currentKey != lastKey) {
|
||
printf("Pressed: %c\n", currentKey);
|
||
lastKey = currentKey;
|
||
} else if (currentKey == '\0') {
|
||
lastKey = '\0';
|
||
}
|
||
}
|
||
}
|