Files
whowechina_aic_pico/firmware/src/main.c
T
2024-02-25 10:29:27 +08:00

282 lines
6.1 KiB
C

/*
* Controller Main
* WHowe <github.com/whowechina>
*/
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "pico/stdio.h"
#include "pico/stdlib.h"
#include "bsp/board.h"
#include "pico/multicore.h"
#include "pico/bootrom.h"
#include "hardware/gpio.h"
#include "hardware/sync.h"
#include "hardware/structs/ioqspi.h"
#include "hardware/structs/sio.h"
#include "board_defs.h"
#include "tusb.h"
#include "usb_descriptors.h"
#include "save.h"
#include "config.h"
#include "cli.h"
#include "commands.h"
#include "light.h"
#include "keypad.h"
#include "nfc.h"
#include "aime.h"
static struct {
uint8_t current[9];
uint8_t reported[9];
uint64_t report_time;
} hid_cardio;
void report_hid_cardio()
{
if (!tud_hid_ready()) {
return;
}
uint64_t now = time_us_64();
if (memcmp(hid_cardio.current, "\0\0\0\0\0\0\0\0\0", 9) != 0) {
light_stimulate();
}
if ((memcmp(hid_cardio.current, hid_cardio.reported, 9) != 0) &&
(now - hid_cardio.report_time > 1000000)) {
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;
}
}
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()
{
while (1) {
if (mutex_try_enter(&core1_io_lock, NULL)) {
light_update();
mutex_exit(&core1_io_lock);
}
cli_fps_count(1);
sleep_us(500);
}
}
void detect_card()
{
static nfc_card_t old_card = { 0 };
nfc_card_t card = nfc_detect_card();
switch (card.card_type) {
case NFC_CARD_MIFARE:
hid_cardio.current[0] = REPORT_ID_EAMU;
hid_cardio.current[1] = 0xe0;
hid_cardio.current[2] = 0x04;
if (card.len == 4) {
memcpy(hid_cardio.current + 3, card.uid, 4);
memcpy(hid_cardio.current + 7, card.uid, 2);
} else if (card.len == 7) {
memcpy(hid_cardio.current + 3, card.uid + 1, 6);
}
break;
case NFC_CARD_FELICA:
hid_cardio.current[0] = REPORT_ID_FELICA;
memcpy(hid_cardio.current + 1, card.uid, 8);
break;
case NFC_CARD_VICINITY:
hid_cardio.current[0] = REPORT_ID_EAMU;
memcpy(hid_cardio.current + 1, card.uid, 8);
break;
default:
memset(hid_cardio.current, 0, 9);
}
if (memcmp(&old_card, &card, sizeof(card)) == 0) {
return;
}
if (card.card_type != NFC_CARD_NONE) {
printf("\n%s:", nfc_card_name(card.card_type));
for (int i = 0; i < card.len; i++) {
printf(" %02x", hid_cardio.current[i + 1]);
}
}
old_card = card;
}
const int aime_intf = 1;
static void cdc_aime_putc(uint8_t byte)
{
tud_cdc_n_write(aime_intf, &byte, 1);
tud_cdc_n_write_flush(aime_intf);
}
static void aime_run()
{
if (tud_cdc_n_available(aime_intf)) {
uint8_t buf[32];
int count = tud_cdc_n_read(aime_intf, buf, sizeof(buf));
for (int i = 0; i < count; i++) {
aime_feed(buf[i]);
}
}
}
void wait_loop()
{
keypad_update();
report_hid_key();
tud_task();
cli_run();
cli_fps_count(0);
}
static void core0_loop()
{
while(1) {
tud_task();
cli_run();
aime_run();
save_loop();
cli_fps_count(0);
keypad_update();
detect_card();
report_usb_hid();
sleep_ms(1);
}
}
void init()
{
tusb_init();
stdio_init_all();
light_init();
keypad_init();
config_init();
mutex_init(&core1_io_lock);
save_init(0xca340a1c, &core1_io_lock);
nfc_init(wait_loop);
aime_init(cdc_aime_putc);
cli_init("aic_pico>", "\n << AIC Pico >>\n"
" https://github.com/whowechina\n\n");
commands_init();
}
/* if certain key pressed when booting, enter update mode */
static void update_check()
{
const uint8_t pins[] = { 10, 11 }; // keypad 00 and *
bool all_pressed = true;
for (int i = 0; i < sizeof(pins); i++) {
uint8_t gpio = pins[i];
gpio_init(gpio);
gpio_set_function(gpio, GPIO_FUNC_SIO);
gpio_set_dir(gpio, GPIO_IN);
gpio_pull_up(gpio);
sleep_ms(1);
if (gpio_get(gpio)) {
all_pressed = false;
break;
}
}
if (all_pressed) {
sleep_ms(100);
reset_usb_boot(0, 2);
return;
}
}
static void sys_init()
{
sleep_ms(50);
set_sys_clock_khz(150000, true);
board_init();
}
int main(void)
{
sys_init();
update_check();
init();
multicore_launch_core1(core1_loop);
core0_loop();
return 0;
}
// Invoked when received GET_REPORT control request
// Application must fill buffer report's content and return its length.
// Return zero will cause the stack to STALL request
uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id,
hid_report_type_t report_type, uint8_t *buffer,
uint16_t reqlen)
{
printf("Get from USB %d-%d\n", report_id, report_type);
return 0;
}
// Invoked when received SET_REPORT control request or
// received data on OUT endpoint ( Report ID = 0, Type = 0 )
void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id,
hid_report_type_t report_type, uint8_t const *buffer,
uint16_t bufsize)
{
}