1
0
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:
whowechina 2023-11-12 20:22:08 +08:00
parent dac7d88d4c
commit 83a8e8e7dc
9 changed files with 209 additions and 25 deletions

BIN
firmware/aic_pico.uf2 Normal file

Binary file not shown.

View File

@ -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})

View File

@ -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
View 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
View 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

View File

@ -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);

View File

@ -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

View File

@ -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",
};

View File

@ -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