1
0
mirror of https://github.com/whowechina/aic_pico.git synced 2024-11-24 05:50:11 +01:00

Light follows aime or bana led commands

This commit is contained in:
whowechina 2024-04-21 16:03:32 +08:00
parent 6eb14a6ed1
commit 924b46ca53
6 changed files with 1074 additions and 947 deletions

View File

@ -1,22 +1,24 @@
/*
* Bandai Namco Protocol
* WHowe <github.com/whowechina>
*/
#ifndef BANA_H
#define BANA_H
#include <stdint.h>
#include <stdbool.h>
/* return true if accepts a byte, false if rejects */
typedef void (*bana_putc_func)(uint8_t byte);
void bana_init(bana_putc_func putc_func);
bool bana_feed(int c);
/* bana activity expires at this time */
uint64_t bana_expire_time();
#endif
/*
* Bandai Namco Protocol
* WHowe <github.com/whowechina>
*/
#ifndef BANA_H
#define BANA_H
#include <stdint.h>
#include <stdbool.h>
/* return true if accepts a byte, false if rejects */
typedef void (*bana_putc_func)(uint8_t byte);
void bana_init(bana_putc_func putc_func);
bool bana_feed(int c);
/* bana activity expires at this time */
uint64_t bana_expire_time();
uint32_t bana_led_color();
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,79 +1,169 @@
/*
* Bandai Namco NFC Reader
* WHowe <github.com/whowechina>
*
* Use NFC Module to read BANA
*/
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include "bsp/board.h"
#include "hardware/gpio.h"
#include "hardware/i2c.h"
#include "nfc.h"
#include "bana.h"
#define BANA_EXPIRE_TIME 5000000ULL
static void putc_trap(uint8_t byte)
{
}
static bana_putc_func bana_putc = putc_trap;
void bana_init(bana_putc_func putc_func)
{
bana_putc = putc_func;
}
/*
static uint8_t mifare_keys[2][6]; // 'KeyA' and 'KeyB'
static union __attribute__((packed)) {
struct {
};
uint8_t raw[256];
} response;
static union __attribute__((packed)) {
struct {
};
uint8_t raw[256];
} request;
struct {
bool active;
uint8_t len;
uint8_t check_sum;
bool escaping;
uint64_t time;
} req_ctx;
*/
typedef struct __attribute__((packed)) {
uint8_t count;
uint8_t type;
uint8_t id_len;
union {
struct {
uint8_t idm[8];
uint8_t pmm[8];
};
uint8_t uid[6];
};
} card_info_t;
static uint64_t expire_time;
bool bana_feed(int c)
{
return true;
}
uint64_t bana_expire_time()
{
return expire_time;
}
/*
* Bandai Namco NFC Reader
* WHowe <github.com/whowechina>
*
* Use NFC Module to read BANA
*/
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include "bsp/board.h"
#include "hardware/gpio.h"
#include "hardware/i2c.h"
#include "nfc.h"
#include "bana.h"
#define BANA_EXPIRE_TIME 5000000ULL
static void putc_trap(uint8_t byte)
{
}
static bana_putc_func bana_putc = putc_trap;
static void bana_puts(const char *str, size_t len)
{
for (size_t i = 0; i < len; i++) {
bana_putc(str[i]);
}
}
void bana_init(bana_putc_func putc_func)
{
bana_putc = putc_func;
}
typedef union __attribute__((packed)) {
struct {
struct {
uint8_t padding[3];
uint8_t len;
uint8_t len_check;
} hdr;
uint8_t dir;
uint8_t cmd;
uint8_t data[0];
};
uint8_t raw[48];
} message_t;
static message_t request, response;
struct {
uint8_t frame_len;
uint32_t time;
} req_ctx;
typedef struct __attribute__((packed)) {
uint8_t count;
uint8_t type;
uint8_t id_len;
union {
struct {
uint8_t idm[8];
uint8_t pmm[8];
};
uint8_t uid[6];
};
} card_info_t;
static uint64_t expire_time;
static void send_response()
{
uint8_t checksum = 0xff;
for (int i = 0; i < response.hdr.len; i++) {
checksum += response.raw[5 + i];
}
memcpy(response.hdr.padding, "\x00\x00\xff", 3);
response.hdr.len_check = ~response.hdr.len + 1;
response.raw[5 + response.hdr.len] = ~checksum;
response.raw[6 + response.hdr.len] = 0;
int total_len = 7 + response.hdr.len;
bana_puts((const char *)response.raw, total_len);
printf("\nResp: %d %d\n", response.hdr.len, response.cmd);
for (int i = 0; i < total_len; i++) {
printf(">%02x", response.raw[i]);
}
}
static void send_simple_response(uint8_t code)
{
response.hdr.len = 2;
response.dir = 0xd5;
response.cmd = code;
send_response();
}
static void send_ack()
{
bana_puts("\x00\x00\xff\x00\xff\x00", 6);
}
static uint32_t led_color = 0;
static void handle_frame()
{
printf("\nBana: %d %02x", request.hdr.len, request.cmd);
if (request.hdr.len == 0) {
send_ack();
return;
}
if (request.hdr.len + 7 != req_ctx.frame_len) {
return;
}
if (request.hdr.len != 0) {
printf("Req: %d %02x", request.hdr.len, request.cmd);
send_simple_response(request.cmd + 1);
}
}
bool bana_feed(int c)
{
uint32_t now = time_us_32();
if ((req_ctx.frame_len == sizeof(request)) ||
(now - req_ctx.time > 100000)) {
req_ctx.frame_len = 0;
}
req_ctx.time = now;
request.raw[req_ctx.frame_len] = c;
req_ctx.frame_len++;
if ((req_ctx.frame_len == 1) && (request.raw[0] == 0x55)) {
req_ctx.frame_len = 0;
} if ((req_ctx.frame_len == 3) &&
(memcmp(request.hdr.padding, "\x00\x00\xff", 3) != 0)) {
request.raw[0] = request.raw[1];
request.raw[1] = request.raw[2];
req_ctx.frame_len--;
} if ((req_ctx.frame_len == 6) && (request.hdr.len == 0)) {
req_ctx.frame_len = 0;
} else if (req_ctx.frame_len == request.hdr.len + 7) {
handle_frame();
req_ctx.frame_len = 0;
expire_time = time_us_64() + BANA_EXPIRE_TIME;
}
return true;
}
uint64_t bana_expire_time()
{
return expire_time;
}
uint32_t bana_led_color()
{
return led_color;
}

View File

@ -237,10 +237,18 @@ void light_init()
}
}
static bool rainbow = true;
void light_set_rainbow(bool enable)
{
rainbow = enable;
}
void light_update()
{
generate_color_wheel();
rainbow_update();
rainbow_fade();
if (rainbow) {
generate_color_wheel();
rainbow_update();
rainbow_fade();
}
drive_led();
}

View File

@ -1,25 +1,27 @@
/*
* RGB LED (WS2812) Strip control
* WHowe <github.com/whowechina>
*/
#ifndef RGB_H
#define RGB_H
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "config.h"
void light_init();
void light_update();
uint32_t rgb32(uint32_t r, uint32_t g, uint32_t b, bool gamma_fix);
uint32_t rgb32_from_hsv(uint8_t h, uint8_t s, uint8_t v);
void light_set_color(unsigned index, uint32_t color);
void light_set_color_all(uint32_t color);
void light_stimulate();
#endif
/*
* RGB LED (WS2812) Strip control
* WHowe <github.com/whowechina>
*/
#ifndef RGB_H
#define RGB_H
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "config.h"
void light_init();
void light_update();
uint32_t rgb32(uint32_t r, uint32_t g, uint32_t b, bool gamma_fix);
uint32_t rgb32_from_hsv(uint8_t h, uint8_t s, uint8_t v);
void light_set_color(unsigned index, uint32_t color);
void light_set_color_all(uint32_t color);
void light_set_rainbow(bool enable);
void light_stimulate();
#endif

View File

@ -1,308 +1,333 @@
/*
* 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);
}
}
static void update_cardio(nfc_card_t *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);
return;
}
printf(" -> CardIO ");
for (int i = 1; i < 9; i++) {
printf("%02X", hid_cardio.current[i]);
}
}
void detect_card()
{
if (time_us_64() < aime_expire_time()) {
return;
}
static nfc_card_t old_card = { 0 };
nfc_rf_field(true);
nfc_card_t card = nfc_detect_card();
nfc_rf_field(false);
if (memcmp(&old_card, &card, sizeof(old_card)) == 0) {
return;
}
old_card = card;
display_card(&card);
update_cardio(&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++) {
if ((aic_cfg->mode & 0xf0) == 0) {
aime_feed(buf[i]);
} else {
//bana_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_i2c(I2C_PORT, I2C_SCL, I2C_SDA, I2C_FREQ);
nfc_init_spi(SPI_PORT, SPI_MISO, SPI_SCK, SPI_MOSI, SPI_RST, SPI_NSS, SPI_BUSY);
nfc_init();
nfc_set_wait_loop(wait_loop);
aime_init(cdc_aime_putc);
aime_virtual_aic(aic_cfg->virtual_aic);
if ((aic_cfg->mode & 0x0f) == 0) {
aime_set_mode(aic_cfg->mode);
}
//bana_init();
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)
{
}
/*
* 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"
#include "bana.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 void light_effect()
{
uint64_t now = time_us_64();
if (now < aime_expire_time()) {
light_set_rainbow(false);
light_set_color_all(aime_led_color());
} else if (now < bana_expire_time()) {
light_set_rainbow(false);
light_set_color_all(bana_led_color());
} else {
light_set_rainbow(true);
}
light_update();
}
static mutex_t core1_io_lock;
static void core1_loop()
{
while (1) {
if (mutex_try_enter(&core1_io_lock, NULL)) {
light_effect();
mutex_exit(&core1_io_lock);
}
cli_fps_count(1);
sleep_us(500);
}
}
static void update_cardio(nfc_card_t *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);
return;
}
printf(" -> CardIO ");
for (int i = 1; i < 9; i++) {
printf("%02X", hid_cardio.current[i]);
}
}
void detect_card()
{
if ((time_us_64() < aime_expire_time()) ||
(time_us_64() < bana_expire_time())) {
return;
}
static nfc_card_t old_card = { 0 };
nfc_rf_field(true);
nfc_card_t card = nfc_detect_card();
nfc_rf_field(false);
if (memcmp(&old_card, &card, sizeof(old_card)) == 0) {
return;
}
old_card = card;
display_card(&card);
update_cardio(&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));
if (count <= 0) {
return;
}
printf("\n> ");
for (int i = 0; i < count; i++) {
printf("|%02x", buf[i]);
if ((aic_cfg->mode & 0xf0) == 0) {
aime_feed(buf[i]);
} else {
bana_feed(buf[i]);
}
}
light_set_color_all(aime_led_color());
}
}
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_i2c(I2C_PORT, I2C_SCL, I2C_SDA, I2C_FREQ);
nfc_init_spi(SPI_PORT, SPI_MISO, SPI_SCK, SPI_MOSI, SPI_RST, SPI_NSS, SPI_BUSY);
nfc_init();
nfc_set_wait_loop(wait_loop);
aime_init(cdc_aime_putc);
aime_virtual_aic(aic_cfg->virtual_aic);
if ((aic_cfg->mode & 0x0f) == 0) {
aime_set_mode(aic_cfg->mode);
}
bana_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)
{
}