102 lines
2.5 KiB
C
102 lines
2.5 KiB
C
#include <stdint.h>
|
|
#include "keypad.h"
|
|
#include "gpio.h"
|
|
#include "RotaryCoder.h"
|
|
#include "time.h"
|
|
|
|
static uint8_t key_status = 0;
|
|
static uint16_t encoder_value = 0;
|
|
static GPIO_TypeDef *ports[] = {
|
|
KEY_1_GPIO_Port,
|
|
KEY_2_GPIO_Port,
|
|
KEY_3_GPIO_Port,
|
|
KEY_4_GPIO_Port,
|
|
KEY_5_GPIO_Port,
|
|
KEY_6_GPIO_Port,
|
|
ENCODER_KEY_GPIO_Port
|
|
};
|
|
static uint16_t pins[] = {
|
|
KEY_1_Pin,
|
|
KEY_2_Pin,
|
|
KEY_3_Pin,
|
|
KEY_4_Pin,
|
|
KEY_5_Pin,
|
|
KEY_6_Pin,
|
|
ENCODER_KEY_Pin
|
|
};
|
|
static uint8_t keys[] = {
|
|
kp_KEY1,
|
|
kp_KEY2,
|
|
kp_KEY3,
|
|
kp_KEY4,
|
|
kp_KEY5,
|
|
kp_KEY6,
|
|
kp_KEYENCODER
|
|
};
|
|
static int32_t pressed_at[] = {
|
|
-1,
|
|
-1,
|
|
-1,
|
|
-1,
|
|
-1,
|
|
-1,
|
|
-1
|
|
};
|
|
|
|
#define K_GET(x) (((0b1 << x) & key_status) >> x)
|
|
#define K_SET0(x) (key_status = (~(0b1 << x)) & key_status)
|
|
#define K_SET1(x) (key_status = (0b1 << x) | key_status)
|
|
#define K_HGET(x) (HAL_GPIO_ReadPin(ports[x], pins[x]) == GPIO_PIN_RESET)
|
|
#define K_EVENT(event, value) ((value << 4) | event)
|
|
|
|
uint8_t kp_query() {
|
|
// Scan keypad
|
|
int32_t now = ticks_ms();
|
|
uint16_t rota_value = EC11_COUNT();
|
|
uint16_t differ = rota_value - encoder_value;
|
|
uint8_t direction = kp_ROTATE_LEFT;
|
|
if (differ > 0) {
|
|
if (differ > 32768) {
|
|
differ = 0xFFFF - differ + 1;
|
|
direction = kp_ROTATE_RIGHT;
|
|
}
|
|
differ = differ / 2; // filter 2x
|
|
}
|
|
if (differ > 0) {
|
|
encoder_value = rota_value;
|
|
return K_EVENT(direction, differ);
|
|
}
|
|
uint8_t state, mstate, key_n;
|
|
for (key_n = 0; key_n < sizeof(keys); key_n ++) {
|
|
state = K_HGET(key_n);
|
|
mstate = K_GET(key_n);
|
|
if (state && (!mstate)) {
|
|
K_SET1(key_n);
|
|
pressed_at[key_n] = now;
|
|
return K_EVENT(kp_KEY_DOWN, keys[key_n]);
|
|
} else if ((!state) && mstate) {
|
|
if (pressed_at[key_n] >= 0) {
|
|
pressed_at[key_n] = -1;
|
|
return K_EVENT(kp_SHORT_CLICK, keys[key_n]);
|
|
}
|
|
K_SET0(key_n);
|
|
return K_EVENT(kp_KEY_UP, keys[key_n]);
|
|
}
|
|
// ticks pressed time
|
|
if (pressed_at[key_n] >= 0 && state) {
|
|
if (ticks_diff(now, pressed_at[key_n]) > kp_LONG_PRESS_TIMEOUT_MS) {
|
|
pressed_at[key_n] = -1;
|
|
return K_EVENT(kp_LONG_PRESS, keys[key_n]);
|
|
}
|
|
}
|
|
}
|
|
return K_EVENT(kp_NOP, 0);
|
|
}
|
|
|
|
void discare_kp_events() {
|
|
uint8_t event = kp_query();
|
|
while (kp_Type(event) != kp_NOP) {
|
|
event = kp_query();
|
|
}
|
|
}
|