mirror of
https://github.com/whowechina/aic_pico.git
synced 2025-02-17 19:09:24 +01:00
Keypad support
This commit is contained in:
parent
dac7d88d4c
commit
83a8e8e7dc
BIN
firmware/aic_pico.uf2
Normal file
BIN
firmware/aic_pico.uf2
Normal file
Binary file not shown.
@ -4,7 +4,7 @@ set(LWIP_ROOT ${PICO_SDK_PATH}/lib/lwip)
|
||||
function(make_firmware board board_def)
|
||||
pico_sdk_init()
|
||||
add_executable(${board}
|
||||
main.c save.c config.c commands.c rgb.c
|
||||
main.c save.c config.c commands.c rgb.c keypad.c
|
||||
aime.c cli.c pn532.c
|
||||
usb_descriptors.c)
|
||||
target_compile_definitions(${board} PUBLIC ${board_def})
|
||||
|
@ -13,6 +13,11 @@
|
||||
#define RGB_PIN 12
|
||||
#define RGB_ORDER GRB // or RGB
|
||||
|
||||
#define KEYPAD_DEF { 6, 7, 8, 3, 4, 5, 0, 1, 2, 9, 10, 11 }
|
||||
/* HID Keycode: https://github.com/hathach/tinyusb/blob/master/src/class/hid/hid.h */
|
||||
// Numpad: 1234567890.(Enter)
|
||||
#define KEYPAD_NKRO_MAP "\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x58"
|
||||
|
||||
#else
|
||||
|
||||
#endif
|
||||
|
75
firmware/src/keypad.c
Normal file
75
firmware/src/keypad.c
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* AIC Pico Keypad
|
||||
* WHowe <github.com/whowechina>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "keypad.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "hardware/gpio.h"
|
||||
#include "hardware/timer.h"
|
||||
#include "hardware/pwm.h"
|
||||
|
||||
#include "board_defs.h"
|
||||
|
||||
static const uint8_t keypad_gpio[] = KEYPAD_DEF;
|
||||
|
||||
#define KEY_NUM (sizeof(keypad_gpio))
|
||||
|
||||
static bool sw_val[KEY_NUM]; /* true if pressed */
|
||||
static uint64_t sw_freeze_time[KEY_NUM];
|
||||
|
||||
void keypad_init()
|
||||
{
|
||||
for (int i = 0; i < KEY_NUM; i++)
|
||||
{
|
||||
sw_val[i] = false;
|
||||
sw_freeze_time[i] = 0;
|
||||
int8_t gpio = keypad_gpio[i];
|
||||
gpio_init(gpio);
|
||||
gpio_set_function(gpio, GPIO_FUNC_SIO);
|
||||
gpio_set_dir(gpio, GPIO_IN);
|
||||
gpio_pull_up(gpio);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t keypad_key_num()
|
||||
{
|
||||
return KEY_NUM;
|
||||
}
|
||||
|
||||
static uint16_t keypad_reading;
|
||||
|
||||
/* If a switch flips, it freezes for a while */
|
||||
#define DEBOUNCE_FREEZE_TIME_US 20000
|
||||
void keypad_update()
|
||||
{
|
||||
uint64_t now = time_us_64();
|
||||
uint16_t keys = 0;
|
||||
|
||||
for (int i = KEY_NUM - 1; i >= 0; i--) {
|
||||
bool sw_pressed = !gpio_get(keypad_gpio[i]);
|
||||
|
||||
if (now >= sw_freeze_time[i]) {
|
||||
if (sw_pressed != sw_val[i]) {
|
||||
sw_val[i] = sw_pressed;
|
||||
sw_freeze_time[i] = now + DEBOUNCE_FREEZE_TIME_US;
|
||||
}
|
||||
}
|
||||
|
||||
keys <<= 1;
|
||||
if (sw_val[i]) {
|
||||
keys |= 1;
|
||||
}
|
||||
}
|
||||
|
||||
keypad_reading = keys;
|
||||
}
|
||||
|
||||
uint16_t keypad_read()
|
||||
{
|
||||
return keypad_reading;
|
||||
}
|
16
firmware/src/keypad.h
Normal file
16
firmware/src/keypad.h
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* AIC Pico Keypad
|
||||
* WHowe <github.com/whowechina>
|
||||
*/
|
||||
|
||||
#ifndef KEYPAD_H
|
||||
#define KEYPAD_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void keypad_init();
|
||||
uint8_t keypad_key_num();
|
||||
void keypad_update();
|
||||
uint16_t keypad_read();
|
||||
|
||||
#endif
|
@ -28,6 +28,7 @@
|
||||
#include "cli.h"
|
||||
#include "commands.h"
|
||||
#include "rgb.h"
|
||||
#include "keypad.h"
|
||||
|
||||
#include "pn532.h"
|
||||
#include "aime.h"
|
||||
@ -36,9 +37,9 @@ static struct {
|
||||
uint8_t current[9];
|
||||
uint8_t reported[9];
|
||||
uint64_t report_time;
|
||||
} cardio;
|
||||
} hid_cardio;
|
||||
|
||||
void report_usb_hid()
|
||||
void report_hid_cardio()
|
||||
{
|
||||
if (!tud_hid_ready()) {
|
||||
return;
|
||||
@ -46,27 +47,60 @@ void report_usb_hid()
|
||||
|
||||
uint64_t now = time_us_64();
|
||||
|
||||
if (memcmp(cardio.current, "\0\0\0\0\0\0\0\0\0", 9) != 0) {
|
||||
if (memcmp(hid_cardio.current, "\0\0\0\0\0\0\0\0\0", 9) != 0) {
|
||||
rgb_set_rainbow_speed(255);
|
||||
}
|
||||
|
||||
if ((memcmp(cardio.current, cardio.reported, 9) != 0) &&
|
||||
(now - cardio.report_time > 1000000)) {
|
||||
if ((memcmp(hid_cardio.current, hid_cardio.reported, 9) != 0) &&
|
||||
(now - hid_cardio.report_time > 1000000)) {
|
||||
|
||||
tud_hid_n_report(0x00, cardio.current[0], cardio.current + 1, 8);
|
||||
memcpy(cardio.reported, cardio.current, 9);
|
||||
cardio.report_time = now;
|
||||
tud_hid_n_report(0x00, hid_cardio.current[0], hid_cardio.current + 1, 8);
|
||||
memcpy(hid_cardio.reported, hid_cardio.current, 9);
|
||||
hid_cardio.report_time = now;
|
||||
|
||||
if (memcmp(cardio.current, "\0\0\0\0\0\0\0\0\0", 9) != 0) {
|
||||
if (memcmp(hid_cardio.current, "\0\0\0\0\0\0\0\0\0", 9) != 0) {
|
||||
printf("Card:");
|
||||
for (int i = 0; i < 9; i++) {
|
||||
printf(" %02x", cardio.current[i]);
|
||||
printf(" %02x", hid_cardio.current[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct __attribute__((packed)) {
|
||||
uint8_t modifier;
|
||||
uint8_t keymap[15];
|
||||
} hid_nkro;
|
||||
|
||||
static const char keymap[12] = KEYPAD_NKRO_MAP;
|
||||
|
||||
void report_hid_key()
|
||||
{
|
||||
if (!tud_hid_ready()) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t keys = keypad_read();
|
||||
for (int i = 0; i < keypad_key_num(); i++) {
|
||||
uint8_t code = keymap[i];
|
||||
uint8_t byte = code / 8;
|
||||
uint8_t bit = code % 8;
|
||||
if (keys & (1 << i)) {
|
||||
hid_nkro.keymap[byte] |= (1 << bit);
|
||||
} else {
|
||||
hid_nkro.keymap[byte] &= ~(1 << bit);
|
||||
}
|
||||
}
|
||||
tud_hid_n_report(1, 0, &hid_nkro, sizeof(hid_nkro));
|
||||
}
|
||||
|
||||
void report_usb_hid()
|
||||
{
|
||||
report_hid_cardio();
|
||||
report_hid_key();
|
||||
}
|
||||
|
||||
static mutex_t core1_io_lock;
|
||||
static void core1_loop()
|
||||
{
|
||||
@ -89,26 +123,26 @@ void detect_card()
|
||||
int len = sizeof(id);
|
||||
bool mifare = pn532_poll_mifare(id, &len);
|
||||
if (mifare) {
|
||||
cardio.current[0] = REPORT_ID_EAMU;
|
||||
cardio.current[1] = 0xe0;
|
||||
cardio.current[2] = 0x04;
|
||||
hid_cardio.current[0] = REPORT_ID_EAMU;
|
||||
hid_cardio.current[1] = 0xe0;
|
||||
hid_cardio.current[2] = 0x04;
|
||||
if (len == 4) {
|
||||
memcpy(cardio.current + 3, id, 4);
|
||||
memcpy(cardio.current + 7, id, 2);
|
||||
memcpy(hid_cardio.current + 3, id, 4);
|
||||
memcpy(hid_cardio.current + 7, id, 2);
|
||||
} else if (len == 7) {
|
||||
memcpy(cardio.current + 3, id + 1, 6);
|
||||
memcpy(hid_cardio.current + 3, id + 1, 6);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool felica = pn532_poll_felica(id, id + 8, id + 16, false);
|
||||
if (felica) {
|
||||
cardio.current[0] = REPORT_ID_FELICA;
|
||||
memcpy(cardio.current + 1, id, 8);
|
||||
hid_cardio.current[0] = REPORT_ID_FELICA;
|
||||
memcpy(hid_cardio.current + 1, id, 8);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(cardio.current, 0, 9);
|
||||
memset(hid_cardio.current, 0, 9);
|
||||
}
|
||||
|
||||
const int aime_intf = 1;
|
||||
@ -131,8 +165,12 @@ static void aime_run()
|
||||
|
||||
void wait_loop()
|
||||
{
|
||||
keypad_update();
|
||||
report_hid_key();
|
||||
|
||||
tud_task();
|
||||
cli_run();
|
||||
|
||||
cli_fps_count(0);
|
||||
}
|
||||
|
||||
@ -147,8 +185,11 @@ static void core0_loop()
|
||||
save_loop();
|
||||
cli_fps_count(0);
|
||||
|
||||
keypad_update();
|
||||
detect_card();
|
||||
|
||||
report_usb_hid();
|
||||
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
@ -161,6 +202,7 @@ void init()
|
||||
tusb_init();
|
||||
stdio_init_all();
|
||||
rgb_init();
|
||||
keypad_init();
|
||||
|
||||
config_init();
|
||||
mutex_init(&core1_io_lock);
|
||||
|
@ -96,7 +96,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
//------------- CLASS -------------//
|
||||
#define CFG_TUD_HID 1
|
||||
#define CFG_TUD_HID 2
|
||||
#define CFG_TUD_CDC 2
|
||||
#define CFG_TUD_MSC 0
|
||||
#define CFG_TUD_MIDI 0
|
||||
|
@ -75,6 +75,10 @@ uint8_t const desc_hid_report_cardio[] = {
|
||||
AIC_PICO_REPORT_DESC_CARDIO,
|
||||
};
|
||||
|
||||
uint8_t const desc_hid_report_nkro[] = {
|
||||
AIC_PICO_REPORT_DESC_NKRO,
|
||||
};
|
||||
|
||||
// Invoked when received GET HID REPORT DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
// Descriptor contents must exist long enough for transfer to complete
|
||||
@ -83,6 +87,8 @@ uint8_t const* tud_hid_descriptor_report_cb(uint8_t itf)
|
||||
switch (itf) {
|
||||
case 0:
|
||||
return desc_hid_report_cardio;
|
||||
case 1:
|
||||
return desc_hid_report_nkro;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
@ -91,14 +97,15 @@ uint8_t const* tud_hid_descriptor_report_cb(uint8_t itf)
|
||||
// Configuration Descriptor
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
enum { ITF_NUM_CARDIO,
|
||||
enum { ITF_NUM_CARDIO, ITF_NUM_NKRO,
|
||||
ITF_NUM_CLI, ITF_NUM_CLI_DATA,
|
||||
ITF_NUM_AIME, ITF_NUM_AIME_DATA,
|
||||
ITF_NUM_TOTAL };
|
||||
|
||||
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_DESC_LEN * 1 + TUD_CDC_DESC_LEN * 2)
|
||||
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_DESC_LEN * 2 + TUD_CDC_DESC_LEN * 2)
|
||||
|
||||
#define EPNUM_CARDIO 0x81
|
||||
#define EPNUM_KEY 0x82
|
||||
|
||||
#define EPNUM_CLI_NOTIF 0x85
|
||||
#define EPNUM_CLI_OUT 0x06
|
||||
@ -120,10 +127,14 @@ uint8_t const desc_configuration_dev[] = {
|
||||
sizeof(desc_hid_report_cardio), EPNUM_CARDIO,
|
||||
CFG_TUD_HID_EP_BUFSIZE, 1),
|
||||
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CLI, 5, EPNUM_CLI_NOTIF,
|
||||
TUD_HID_DESCRIPTOR(ITF_NUM_NKRO, 5, HID_ITF_PROTOCOL_NONE,
|
||||
sizeof(desc_hid_report_nkro), EPNUM_KEY,
|
||||
CFG_TUD_HID_EP_BUFSIZE, 1),
|
||||
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CLI, 6, EPNUM_CLI_NOTIF,
|
||||
8, EPNUM_CLI_OUT, EPNUM_CLI_IN, 64),
|
||||
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_AIME, 6, EPNUM_AIME_NOTIF,
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_AIME, 7, EPNUM_AIME_NOTIF,
|
||||
8, EPNUM_AIME_OUT, EPNUM_AIME_IN, 64),
|
||||
};
|
||||
|
||||
@ -147,6 +158,7 @@ const char *string_desc_arr[] = {
|
||||
"AIC Pico", // 2: Product
|
||||
serial_number_str, // 3: Serials, should use chip ID
|
||||
"AIC Pico CardIO",
|
||||
"AIC Pico Keypad",
|
||||
"AIC Pico CLI Port",
|
||||
"AIC Pico AIME Port",
|
||||
};
|
||||
|
@ -28,4 +28,38 @@ enum {
|
||||
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
|
||||
HID_COLLECTION_END
|
||||
|
||||
#define AIC_PICO_REPORT_DESC_NKRO \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
|
||||
HID_USAGE(HID_USAGE_DESKTOP_KEYBOARD), \
|
||||
HID_COLLECTION(HID_COLLECTION_APPLICATION), \
|
||||
/* Modifier */ \
|
||||
HID_REPORT_SIZE(1), \
|
||||
HID_REPORT_COUNT(8), \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_KEYBOARD), \
|
||||
HID_USAGE_MIN(224), \
|
||||
HID_USAGE_MAX(231), \
|
||||
HID_LOGICAL_MIN(0), \
|
||||
HID_LOGICAL_MAX(1), \
|
||||
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
|
||||
/* LED output that we don't care */ \
|
||||
HID_REPORT_COUNT(5), \
|
||||
HID_REPORT_SIZE(1), \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_LED), \
|
||||
HID_USAGE_MIN(1), \
|
||||
HID_USAGE_MAX(5), \
|
||||
HID_OUTPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
|
||||
HID_REPORT_COUNT(1), \
|
||||
HID_REPORT_SIZE(3), \
|
||||
HID_OUTPUT(HID_CONSTANT), \
|
||||
/* Full Keyboard Bitmap */ \
|
||||
HID_REPORT_SIZE(1), \
|
||||
HID_REPORT_COUNT(120), \
|
||||
HID_LOGICAL_MIN(0), \
|
||||
HID_LOGICAL_MAX(1), \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_KEYBOARD), \
|
||||
HID_USAGE_MIN(0), \
|
||||
HID_USAGE_MAX(119), \
|
||||
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
|
||||
HID_COLLECTION_END
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user