mirror of
https://github.com/whowechina/mai_pico.git
synced 2025-02-17 18:08:30 +01:00
Touch working, 3 CDC interfaces now
This commit is contained in:
parent
5eb5da42e2
commit
fec2f5e6f7
@ -4,8 +4,8 @@ set(LWIP_ROOT ${PICO_SDK_PATH}/lib/lwip)
|
||||
function(make_firmware board board_def)
|
||||
pico_sdk_init()
|
||||
add_executable(${board}
|
||||
main.c touch.c rgb.c save.c config.c cmd.c
|
||||
mpr121.c usb_descriptors.c)
|
||||
main.c touch.c rgb.c save.c config.c cli.c commands.c mpr121.c
|
||||
usb_descriptors.c)
|
||||
target_compile_definitions(${board} PUBLIC ${board_def})
|
||||
pico_enable_stdio_usb(${board} 1)
|
||||
pico_enable_stdio_uart(${board} 0)
|
||||
|
@ -5,12 +5,12 @@
|
||||
|
||||
#if defined BOARD_MAI_PICO
|
||||
|
||||
#define I2C_PORT i2c0
|
||||
#define I2C_SDA 16
|
||||
#define I2C_SCL 17
|
||||
#define I2C_FREQ 733*1000
|
||||
#define I2C_PORT i2c1
|
||||
#define I2C_SDA 6
|
||||
#define I2C_SCL 7
|
||||
#define I2C_FREQ 400*1000
|
||||
|
||||
#define RGB_PIN 2
|
||||
#define RGB_PIN 13
|
||||
#define RGB_ORDER GRB // or RGB
|
||||
|
||||
#define NKRO_KEYMAP "1aqz2swx3dec4frv5gtb6hyn7jum8ki90olp,."
|
||||
|
182
firmware/src/cli.c
Normal file
182
firmware/src/cli.c
Normal file
@ -0,0 +1,182 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "pico/stdio.h"
|
||||
#include "pico/stdlib.h"
|
||||
#include "cli.h"
|
||||
|
||||
#define MAX_COMMANDS 32
|
||||
#define MAX_PARAMETERS 6
|
||||
#define MAX_PARAMETER_LENGTH 20
|
||||
|
||||
const char *cli_prompt = "cli>";
|
||||
const char *cli_logo = "CLI";
|
||||
|
||||
static const char *commands[MAX_COMMANDS];
|
||||
static const char *helps[MAX_COMMANDS];
|
||||
static cmd_handler_t handlers[MAX_COMMANDS];
|
||||
static int max_cmd_len = 0;
|
||||
|
||||
static int num_commands = 0;
|
||||
|
||||
void cli_register(const char *cmd, cmd_handler_t handler, const char *help)
|
||||
{
|
||||
if (num_commands < MAX_COMMANDS) {
|
||||
commands[num_commands] = cmd;
|
||||
handlers[num_commands] = handler;
|
||||
helps[num_commands] = help;
|
||||
num_commands++;
|
||||
if (strlen(cmd) > max_cmd_len) {
|
||||
max_cmd_len = strlen(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return -1 if not matched, return -2 if ambiguous
|
||||
int cli_match_prefix(const char *str[], int num, const char *prefix)
|
||||
{
|
||||
int match = -1;
|
||||
bool found = false;
|
||||
|
||||
for (int i = 0; (i < num) && str[i]; i++) {
|
||||
if (strncasecmp(str[i], prefix, strlen(prefix)) == 0) {
|
||||
if (found) {
|
||||
return -2;
|
||||
}
|
||||
found = true;
|
||||
match = i;
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
static void handle_help(int argc, char *argv[])
|
||||
{
|
||||
printf("%s", cli_logo);
|
||||
printf("Available commands:\n");
|
||||
for (int i = 0; i < num_commands; i++) {
|
||||
printf("%*s: %s\n", max_cmd_len + 2, commands[i], helps[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static int fps[2];
|
||||
void cli_fps_count(int core)
|
||||
{
|
||||
static uint32_t last[2] = {0};
|
||||
static int counter[2] = {0};
|
||||
|
||||
counter[core]++;
|
||||
|
||||
uint32_t now = time_us_32();
|
||||
if (now - last[core] < 1000000) {
|
||||
return;
|
||||
}
|
||||
last[core] = now;
|
||||
fps[core] = counter[core];
|
||||
counter[core] = 0;
|
||||
}
|
||||
|
||||
static void handle_fps(int argc, char *argv[])
|
||||
{
|
||||
printf("FPS: core 0: %d, core 1: %d\n", fps[0], fps[1]);
|
||||
}
|
||||
|
||||
int cli_extract_non_neg_int(const char *param, int len)
|
||||
{
|
||||
if (len == 0) {
|
||||
len = strlen(param);
|
||||
}
|
||||
int result = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (!isdigit(param[i])) {
|
||||
return -1;
|
||||
}
|
||||
result = result * 10 + param[i] - '0';
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static char cmd_buf[256];
|
||||
static int cmd_len = 0;
|
||||
|
||||
static void process_cmd()
|
||||
{
|
||||
char *argv[MAX_PARAMETERS];
|
||||
int argc;
|
||||
|
||||
char *cmd = strtok(cmd_buf, " \n");
|
||||
|
||||
if (strlen(cmd) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
argc = 0;
|
||||
while ((argc < MAX_PARAMETERS) &&
|
||||
(argv[argc] = strtok(NULL, " ,\n")) != NULL) {
|
||||
argc++;
|
||||
}
|
||||
|
||||
int match = cli_match_prefix(commands, num_commands, cmd);
|
||||
if (match == -2) {
|
||||
printf("Ambiguous command.\n");
|
||||
return;
|
||||
} else if (match == -1) {
|
||||
printf("Unknown command.\n");
|
||||
handle_help(0, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
handlers[match](argc, argv);
|
||||
}
|
||||
|
||||
void cli_run()
|
||||
{
|
||||
int c = getchar_timeout_us(0);
|
||||
if (c == EOF) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (c == '\b' || c == 127) { // both backspace and delete
|
||||
if (cmd_len > 0) {
|
||||
cmd_len--;
|
||||
printf("\b \b");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ((c != '\n') && (c != '\r')) {
|
||||
|
||||
if (cmd_len < sizeof(cmd_buf) - 2) {
|
||||
cmd_buf[cmd_len] = c;
|
||||
printf("%c", c);
|
||||
cmd_len++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
cmd_buf[cmd_len] = '\0';
|
||||
cmd_len = 0;
|
||||
|
||||
printf("\n");
|
||||
|
||||
process_cmd();
|
||||
|
||||
printf(cli_prompt);
|
||||
}
|
||||
|
||||
void cli_init(const char *prompt, const char *logo)
|
||||
{
|
||||
if (prompt) {
|
||||
cli_prompt = prompt;
|
||||
}
|
||||
if (logo) {
|
||||
cli_logo = logo;
|
||||
}
|
||||
|
||||
cli_register("?", handle_help, "Display this help message.");
|
||||
cli_register("fps", handle_fps, "Display FPS.");
|
||||
}
|
20
firmware/src/cli.h
Normal file
20
firmware/src/cli.h
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Chu Controller Command Line Framework
|
||||
* WHowe <github.com/whowechina>
|
||||
*/
|
||||
|
||||
#ifndef CLI_H
|
||||
#define CLI_H
|
||||
|
||||
|
||||
typedef void (*cmd_handler_t)(int argc, char *argv[]);
|
||||
|
||||
void cli_init();
|
||||
void cli_register(const char *cmd, cmd_handler_t handler, const char *help);
|
||||
void cli_run();
|
||||
void cli_fps_count(int core);
|
||||
|
||||
int cli_extract_non_neg_int(const char *param, int len);
|
||||
int cli_match_prefix(const char *str[], int num, const char *prefix);
|
||||
|
||||
#endif
|
@ -1,13 +0,0 @@
|
||||
/*
|
||||
* Mai Controller Command Line
|
||||
* WHowe <github.com/whowechina>
|
||||
*/
|
||||
|
||||
#ifndef CMD_H
|
||||
#define CMD_H
|
||||
|
||||
void cmd_init();
|
||||
void cmd_run();
|
||||
void fps_count(int core);
|
||||
|
||||
#endif
|
341
firmware/src/commands.c
Normal file
341
firmware/src/commands.c
Normal file
@ -0,0 +1,341 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "pico/stdio.h"
|
||||
#include "pico/stdlib.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "save.h"
|
||||
#include "cli.h"
|
||||
|
||||
#define SENSE_LIMIT_MAX 9
|
||||
#define SENSE_LIMIT_MIN -9
|
||||
|
||||
static void disp_colors()
|
||||
{
|
||||
printf("[Colors]\n");
|
||||
printf(" Key upper: %06x, lower: %06x, both: %06x, off: %06x\n",
|
||||
mai_cfg->colors.key_on_upper, mai_cfg->colors.key_on_lower,
|
||||
mai_cfg->colors.key_on_both, mai_cfg->colors.key_off);
|
||||
printf(" Gap: %06x\n", mai_cfg->colors.gap);
|
||||
}
|
||||
|
||||
static void disp_style()
|
||||
{
|
||||
printf("[Style]\n");
|
||||
printf(" Key: %d, Gap: %d, ToF: %d, Level: %d\n",
|
||||
mai_cfg->style.key, mai_cfg->style.gap,
|
||||
mai_cfg->style.tof, mai_cfg->style.level);
|
||||
}
|
||||
|
||||
static void disp_sense()
|
||||
{
|
||||
printf("[Sense]\n");
|
||||
printf(" Filter: %u, %u, %u\n", mai_cfg->sense.filter >> 6,
|
||||
(mai_cfg->sense.filter >> 4) & 0x03,
|
||||
mai_cfg->sense.filter & 0x07);
|
||||
printf(" Sensitivity (global: %+d):\n", mai_cfg->sense.global);
|
||||
printf(" | 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13|14|15|16|\n");
|
||||
printf(" ---------------------------------------------------\n");
|
||||
printf(" A |");
|
||||
for (int i = 0; i < 16; i++) {
|
||||
printf("%+2d|", mai_cfg->sense.keys[i * 2]);
|
||||
}
|
||||
printf("\n B |");
|
||||
for (int i = 0; i < 16; i++) {
|
||||
printf("%+2d|", mai_cfg->sense.keys[i * 2 + 1]);
|
||||
}
|
||||
printf("\n");
|
||||
printf(" Debounce (touch, release): %d, %d\n",
|
||||
mai_cfg->sense.debounce_touch, mai_cfg->sense.debounce_release);
|
||||
}
|
||||
|
||||
static void disp_hid()
|
||||
{
|
||||
printf("[HID]\n");
|
||||
printf(" Joy: %s, NKRO: %s.\n",
|
||||
mai_cfg->hid.joy ? "on" : "off",
|
||||
mai_cfg->hid.nkro ? "on" : "off" );
|
||||
}
|
||||
|
||||
void handle_display(int argc, char *argv[])
|
||||
{
|
||||
const char *usage = "Usage: display [colors|style|tof|sense|hid]\n";
|
||||
if (argc > 1) {
|
||||
printf(usage);
|
||||
return;
|
||||
}
|
||||
|
||||
if (argc == 0) {
|
||||
disp_colors();
|
||||
disp_style();
|
||||
disp_sense();
|
||||
disp_hid();
|
||||
return;
|
||||
}
|
||||
|
||||
const char *choices[] = {"colors", "style", "sense", "hid"};
|
||||
switch (cli_match_prefix(choices, 5, argv[0])) {
|
||||
case 0:
|
||||
disp_colors();
|
||||
break;
|
||||
case 1:
|
||||
disp_style();
|
||||
break;
|
||||
case 2:
|
||||
disp_sense();
|
||||
break;
|
||||
case 3:
|
||||
disp_hid();
|
||||
break;
|
||||
default:
|
||||
printf(usage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_level(int argc, char *argv[])
|
||||
{
|
||||
const char *usage = "Usage: level <0..255>\n";
|
||||
if (argc != 1) {
|
||||
printf(usage);
|
||||
return;
|
||||
}
|
||||
|
||||
int level = cli_extract_non_neg_int(argv[0], 0);
|
||||
if ((level < 0) || (level > 255)) {
|
||||
printf(usage);
|
||||
return;
|
||||
}
|
||||
|
||||
mai_cfg->style.level = level;
|
||||
config_changed();
|
||||
disp_style();
|
||||
}
|
||||
|
||||
static void handle_stat(int argc, char *argv[])
|
||||
{
|
||||
if (argc == 0) {
|
||||
for (int col = 0; col < 4; col++) {
|
||||
printf(" %2dA |", col * 4 + 1);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
printf("%6u|", touch_count(col * 8 + i * 2));
|
||||
}
|
||||
printf("\n B |");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
printf("%6u|", touch_count(col * 8 + i * 2 + 1));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
} else if ((argc == 1) &&
|
||||
(strncasecmp(argv[0], "reset", strlen(argv[0])) == 0)) {
|
||||
touch_reset_stat();
|
||||
} else {
|
||||
printf("Usage: stat [reset]\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_hid(int argc, char *argv[])
|
||||
{
|
||||
const char *usage = "Usage: hid <joy|nkro|both>\n";
|
||||
if (argc != 1) {
|
||||
printf(usage);
|
||||
return;
|
||||
}
|
||||
|
||||
const char *choices[] = {"joy", "nkro", "both"};
|
||||
int match = cli_match_prefix(choices, 3, argv[0]);
|
||||
if (match < 0) {
|
||||
printf(usage);
|
||||
return;
|
||||
}
|
||||
|
||||
mai_cfg->hid.joy = ((match == 0) || (match == 2)) ? 1 : 0;
|
||||
mai_cfg->hid.nkro = ((match == 1) || (match == 2)) ? 1 : 0;
|
||||
config_changed();
|
||||
disp_hid();
|
||||
}
|
||||
|
||||
static void handle_filter(int argc, char *argv[])
|
||||
{
|
||||
const char *usage = "Usage: filter <first> <second> [interval]\n"
|
||||
" first: First iteration [0..3]\n"
|
||||
" second: Second iteration [0..3]\n"
|
||||
" interval: Interval of second iterations [0..7]\n";
|
||||
if ((argc < 2) || (argc > 3)) {
|
||||
printf(usage);
|
||||
return;
|
||||
}
|
||||
|
||||
int ffi = cli_extract_non_neg_int(argv[0], 0);
|
||||
int sfi = cli_extract_non_neg_int(argv[1], 0);
|
||||
int intv = mai_cfg->sense.filter & 0x07;
|
||||
if (argc == 3) {
|
||||
intv = cli_extract_non_neg_int(argv[2], 0);
|
||||
}
|
||||
|
||||
if ((ffi < 0) || (ffi > 3) || (sfi < 0) || (sfi > 3) ||
|
||||
(intv < 0) || (intv > 7)) {
|
||||
printf(usage);
|
||||
return;
|
||||
}
|
||||
|
||||
mai_cfg->sense.filter = (ffi << 6) | (sfi << 4) | intv;
|
||||
|
||||
touch_update_config();
|
||||
config_changed();
|
||||
disp_sense();
|
||||
}
|
||||
|
||||
static uint8_t *extract_key(const char *param)
|
||||
{
|
||||
int len = strlen(param);
|
||||
|
||||
int offset;
|
||||
if (toupper(param[len - 1]) == 'A') {
|
||||
offset = 0;
|
||||
} else if (toupper(param[len - 1]) == 'B') {
|
||||
offset = 1;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int id = cli_extract_non_neg_int(param, len - 1) - 1;
|
||||
if ((id < 0) || (id > 15)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &mai_cfg->sense.keys[id * 2 + offset];
|
||||
}
|
||||
|
||||
static void sense_do_op(int8_t *target, char op)
|
||||
{
|
||||
if (op == '+') {
|
||||
if (*target < SENSE_LIMIT_MAX) {
|
||||
(*target)++;
|
||||
}
|
||||
} else if (op == '-') {
|
||||
if (*target > SENSE_LIMIT_MIN) {
|
||||
(*target)--;
|
||||
}
|
||||
} else if (op == '0') {
|
||||
*target = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_sense(int argc, char *argv[])
|
||||
{
|
||||
const char *usage = "Usage: sense [key|*] <+|-|0>\n"
|
||||
"Example:\n"
|
||||
" >sense +\n"
|
||||
" >sense -\n"
|
||||
" >sense 1A +\n"
|
||||
" >sense 13B -\n";
|
||||
" >sense * 0\n";
|
||||
if ((argc < 1) || (argc > 2)) {
|
||||
printf(usage);
|
||||
return;
|
||||
}
|
||||
|
||||
const char *op = argv[argc - 1];
|
||||
if ((strlen(op) != 1) || !strchr("+-0", op[0])) {
|
||||
printf(usage);
|
||||
return;
|
||||
}
|
||||
|
||||
if (argc == 1) {
|
||||
sense_do_op(&mai_cfg->sense.global, op[0]);
|
||||
} else {
|
||||
if (strcmp(argv[0], "*") == 0) {
|
||||
for (int i = 0; i < 32; i++) {
|
||||
sense_do_op(&mai_cfg->sense.keys[i], op[0]);
|
||||
}
|
||||
} else {
|
||||
uint8_t *key = extract_key(argv[0]);
|
||||
if (!key) {
|
||||
printf(usage);
|
||||
return;
|
||||
}
|
||||
sense_do_op(key, op[0]);
|
||||
}
|
||||
}
|
||||
|
||||
touch_update_config();
|
||||
config_changed();
|
||||
disp_sense();
|
||||
}
|
||||
|
||||
static void handle_debounce(int argc, char *argv[])
|
||||
{
|
||||
const char *usage = "Usage: debounce <touch> [release]\n"
|
||||
" touch, release: 0..7\n";
|
||||
if ((argc < 1) || (argc > 2)) {
|
||||
printf(usage);
|
||||
return;
|
||||
}
|
||||
|
||||
int touch = mai_cfg->sense.debounce_touch;
|
||||
int release = mai_cfg->sense.debounce_release;
|
||||
if (argc >= 1) {
|
||||
touch = cli_extract_non_neg_int(argv[0], 0);
|
||||
}
|
||||
if (argc == 2) {
|
||||
release = cli_extract_non_neg_int(argv[1], 0);
|
||||
}
|
||||
|
||||
if ((touch < 0) || (release < 0) ||
|
||||
(touch > 7) || (release > 7)) {
|
||||
printf(usage);
|
||||
return;
|
||||
}
|
||||
|
||||
mai_cfg->sense.debounce_touch = touch;
|
||||
mai_cfg->sense.debounce_release = release;
|
||||
|
||||
touch_update_config();
|
||||
config_changed();
|
||||
disp_sense();
|
||||
}
|
||||
|
||||
static void handle_raw()
|
||||
{
|
||||
printf("Key raw readings:\n");
|
||||
const uint16_t *raw = touch_raw();
|
||||
printf("|");
|
||||
for (int i = 0; i < 16; i++) {
|
||||
printf("%3d|", raw[i * 2]);
|
||||
}
|
||||
printf("\n|");
|
||||
for (int i = 0; i < 16; i++) {
|
||||
printf("%3d|", raw[i * 2 + 1]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void handle_save()
|
||||
{
|
||||
save_request(true);
|
||||
}
|
||||
|
||||
static void handle_factory_reset()
|
||||
{
|
||||
config_factory_reset();
|
||||
printf("Factory reset done.\n");
|
||||
}
|
||||
|
||||
void commands_init()
|
||||
{
|
||||
cli_register("display", handle_display, "Display all config.");
|
||||
cli_register("level", handle_level, "Set LED brightness level.");
|
||||
cli_register("stat", handle_stat, "Display or reset statistics.");
|
||||
cli_register("hid", handle_hid, "Set HID mode.");
|
||||
cli_register("filter", handle_filter, "Set pre-filter config.");
|
||||
cli_register("sense", handle_sense, "Set sensitivity config.");
|
||||
cli_register("debounce", handle_debounce, "Set debounce config.");
|
||||
cli_register("raw", handle_raw, "Show key raw readings.");
|
||||
cli_register("save", handle_save, "Save config to flash.");
|
||||
cli_register("factory", config_factory_reset, "Reset everything to default.");
|
||||
}
|
11
firmware/src/commands.h
Normal file
11
firmware/src/commands.h
Normal file
@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Chu Controller Command Line Commands
|
||||
* WHowe <github.com/whowechina>
|
||||
*/
|
||||
|
||||
#ifndef COMMANDS_H
|
||||
#define COMMANDS_H
|
||||
|
||||
void commands_init();
|
||||
|
||||
#endif
|
@ -13,15 +13,24 @@ mai_cfg_t *mai_cfg;
|
||||
|
||||
static mai_cfg_t default_cfg = {
|
||||
.colors = {
|
||||
.key_on = 0x00FF00,
|
||||
.key_on_upper = 0x00FF00,
|
||||
.key_on_lower = 0xff0000,
|
||||
.key_on_both = 0xff0000,
|
||||
.key_off = 0x000000,
|
||||
.gap = 0x000000,
|
||||
},
|
||||
.style = {
|
||||
.key = 0,
|
||||
.level = 7,
|
||||
.gap = 0,
|
||||
.tof = 0,
|
||||
.level = 127,
|
||||
},
|
||||
.tof = {
|
||||
.offset = 100,
|
||||
.pitch = 28,
|
||||
},
|
||||
.sense = {
|
||||
.filter = 0x11,
|
||||
.filter = 0x10,
|
||||
.debounce_touch = 1,
|
||||
.debounce_release = 2,
|
||||
},
|
||||
@ -39,6 +48,11 @@ static void config_loaded()
|
||||
mai_cfg->style.level = default_cfg.style.level;
|
||||
config_changed();
|
||||
}
|
||||
if ((mai_cfg->tof.offset < 40) ||
|
||||
(mai_cfg->tof.pitch < 4) || (mai_cfg->tof.pitch > 50)) {
|
||||
mai_cfg->tof = default_cfg.tof;
|
||||
config_changed();
|
||||
}
|
||||
if ((mai_cfg->sense.filter & 0x0f) > 3 ||
|
||||
((mai_cfg->sense.filter >> 4) & 0x0f) > 3) {
|
||||
mai_cfg->sense.filter = default_cfg.sense.filter;
|
||||
|
@ -11,19 +11,28 @@
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
struct {
|
||||
uint32_t key_on;
|
||||
uint32_t key_on_upper;
|
||||
uint32_t key_on_lower;
|
||||
uint32_t key_on_both;
|
||||
uint32_t key_off;
|
||||
uint32_t gap;
|
||||
} colors;
|
||||
struct {
|
||||
uint8_t key;
|
||||
uint8_t gap;
|
||||
uint8_t tof;
|
||||
uint8_t level;
|
||||
} style;
|
||||
struct {
|
||||
uint8_t offset;
|
||||
uint8_t pitch;
|
||||
} tof;
|
||||
struct {
|
||||
int8_t filter;
|
||||
int8_t global;
|
||||
uint8_t debounce_touch;
|
||||
uint8_t debounce_release;
|
||||
int8_t keys[34];
|
||||
uint8_t debounce_release;
|
||||
int8_t keys[32];
|
||||
} sense;
|
||||
struct {
|
||||
uint8_t joy : 4;
|
||||
|
@ -23,11 +23,12 @@
|
||||
|
||||
#include "board_defs.h"
|
||||
|
||||
#include "touch.h"
|
||||
#include "save.h"
|
||||
#include "config.h"
|
||||
#include "cmd.h"
|
||||
#include "cli.h"
|
||||
#include "commands.h"
|
||||
|
||||
#include "touch.h"
|
||||
#include "rgb.h"
|
||||
|
||||
struct __attribute__((packed)) {
|
||||
@ -71,7 +72,6 @@ static void gen_joy_report()
|
||||
|
||||
}
|
||||
hid_joy.axis ^= 0x80808080; // some magic number from CrazyRedMachine
|
||||
hid_joy.buttons = 0x0;
|
||||
}
|
||||
|
||||
const uint8_t keycode_table[128][2] = { HID_ASCII_TO_KEYCODE };
|
||||
@ -109,21 +109,68 @@ static void run_lights()
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t colors[] = {0x000000, 0x0000ff, 0xff0000, 0xffff00,
|
||||
0x00ff00, 0x00ffff, 0xffffff};
|
||||
uint32_t colors[5] = { 0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0xffffff };
|
||||
|
||||
for (int i = 0; i < 15; i++) {
|
||||
int x = 15 - i;
|
||||
uint8_t r = (x & 0x01) ? 10 : 0;
|
||||
uint8_t g = (x & 0x02) ? 10 : 0;
|
||||
uint8_t b = (x & 0x04) ? 10 : 0;
|
||||
rgb_gap_color(i, rgb32(r, g, b, false));
|
||||
for (int i = 0; i < 8; i++) {
|
||||
rgb_set_color(i, 0);
|
||||
}
|
||||
for (int i = 0; i < 34; i++) {
|
||||
if (touch_touched(i)) {
|
||||
if (i < 32) {
|
||||
rgb_set_color((i + 16) / 4 % 8, colors[i % 4]);
|
||||
} else {
|
||||
rgb_set_color(i - 32, colors[4]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// for (int i = 0; i < 15; i++) {
|
||||
// uint32_t color = rgb32_from_hsv(i * 255 / 8, 255, 16);
|
||||
// rgb_set_color(i, color);
|
||||
// }
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
bool r = touch_touched(i * 2);
|
||||
bool g = touch_touched(i * 2 + 1);
|
||||
rgb_set_color(30 - i * 2, rgb32(r ? 80 : 0, g ? 80 : 0, 0, false));
|
||||
for (int i = 0; i < 34; i++) {
|
||||
// bool r = touch_touched(i * 2);
|
||||
// bool g = touch_touched(i * 2 + 1);
|
||||
// rgb_set_color(30 - i * 2, rgb32(r ? 80 : 0, g ? 80 : 0, 0, false));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void echo_serial_port(uint8_t itf, uint8_t buf[], uint32_t count)
|
||||
{
|
||||
//tud_cdc_n_write_char(itf, buf[i]);
|
||||
//tud_cdc_n_write_flush(itf);
|
||||
}
|
||||
|
||||
static void cdc_task(void)
|
||||
{
|
||||
uint8_t itf;
|
||||
|
||||
for (itf = 1; itf < CFG_TUD_CDC; itf++)
|
||||
{
|
||||
// connected() check for DTR bit
|
||||
// Most but not all terminal client set this when making connection
|
||||
// if ( tud_cdc_n_connected(itf) )
|
||||
if ( tud_cdc_n_available(itf) )
|
||||
{
|
||||
uint8_t buf[64];
|
||||
|
||||
uint32_t count = tud_cdc_n_read(itf, buf, sizeof(buf));
|
||||
|
||||
if (itf == 1) {
|
||||
printf("1 TXT:", itf);
|
||||
for (int i = 0; i < count; i++) {
|
||||
printf("%c", buf[i]);
|
||||
}
|
||||
printf("\n");
|
||||
} else if (itf == 2) {
|
||||
printf("2 HEX:", itf);
|
||||
for (int i = 0; i < count; i++) {
|
||||
printf(" %02x", buf[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,7 +183,7 @@ static void core1_loop()
|
||||
rgb_update();
|
||||
mutex_exit(&core1_io_lock);
|
||||
}
|
||||
fps_count(1);
|
||||
cli_fps_count(1);
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
@ -144,22 +191,24 @@ static void core1_loop()
|
||||
static void core0_loop()
|
||||
{
|
||||
while(1) {
|
||||
cmd_run();
|
||||
tud_task();
|
||||
cdc_task();
|
||||
|
||||
cli_run();
|
||||
save_loop();
|
||||
fps_count(0);
|
||||
cli_fps_count(0);
|
||||
|
||||
touch_update();
|
||||
|
||||
gen_joy_report();
|
||||
gen_nkro_report();
|
||||
report_usb_hid();
|
||||
tud_task();
|
||||
}
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
sleep_ms(100);
|
||||
sleep_ms(50);
|
||||
set_sys_clock_khz(150000, true);
|
||||
board_init();
|
||||
tusb_init();
|
||||
@ -172,7 +221,9 @@ void init()
|
||||
touch_init();
|
||||
rgb_init();
|
||||
|
||||
cmd_init();
|
||||
cli_init("mai_pico>", "\n << Mai Pico Controller >>\n"
|
||||
" https://github.com/whowechina\n\n");
|
||||
commands_init();
|
||||
}
|
||||
|
||||
int main(void)
|
||||
@ -201,13 +252,6 @@ void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id,
|
||||
uint16_t bufsize)
|
||||
{
|
||||
if (report_type == HID_REPORT_TYPE_OUTPUT) {
|
||||
if (report_id == REPORT_ID_LED_touch_16) {
|
||||
rgb_set_brg(0, buffer, bufsize / 3);
|
||||
} else if (report_id == REPORT_ID_LED_touch_15) {
|
||||
rgb_set_brg(16, buffer, bufsize / 3);
|
||||
} else if (report_id == REPORT_ID_LED_TOWER_6) {
|
||||
rgb_set_brg(31, buffer, bufsize / 3);
|
||||
}
|
||||
last_hid_time = time_us_64();
|
||||
return;
|
||||
}
|
||||
|
@ -12,8 +12,8 @@
|
||||
|
||||
#define IO_TIMEOUT_US 1000
|
||||
|
||||
#define TOUCH_THRESHOLD_BASE 17
|
||||
#define RELEASE_THRESHOLD_BASE 12
|
||||
#define TOUCH_THRESHOLD_BASE 22
|
||||
#define RELEASE_THRESHOLD_BASE 15
|
||||
|
||||
#define MPR121_TOUCH_STATUS_REG 0x00
|
||||
#define MPR121_OUT_OF_RANGE_STATUS_0_REG 0x02
|
||||
@ -121,10 +121,14 @@ void mpr121_init(uint8_t i2c_addr)
|
||||
// if only use 0.5uS CDT, the TGL for proximity cannot meet
|
||||
// Possible if manually set Register0x72=0x03
|
||||
// (Auto configure result) alone.
|
||||
write_reg(i2c_addr, 0x7D, 0xc8); // AC up limit /C8/BD/C0/9C
|
||||
write_reg(i2c_addr, 0x7E, 0x82); // AC low limit /82/7A/7C/65
|
||||
write_reg(i2c_addr, 0x7F, 0xb4); // AC target /B4/AA/AC/8C target for /3.0V/2.8V/1.8V
|
||||
write_reg(i2c_addr, 0x5E, 0x8C); // Run 12 touch, CL=2b10, load 5MSB to baseline
|
||||
|
||||
// I want to max out sensitivity, I don't care linearity
|
||||
const uint8_t usl = (3.3 - 0.1) / 3.3 * 256;
|
||||
write_reg(i2c_addr, 0x7D, usl),
|
||||
write_reg(i2c_addr, 0x7E, usl * 0.65),
|
||||
write_reg(i2c_addr, 0x7F, usl * 0.9);
|
||||
|
||||
write_reg(i2c_addr, 0x5E, 0x8C); // Run 12 touch, load 5MSB to baseline
|
||||
}
|
||||
|
||||
#define ABS(x) ((x) < 0 ? -(x) : (x))
|
||||
@ -153,6 +157,11 @@ uint16_t mpr121_touched(uint8_t addr)
|
||||
return touched;
|
||||
}
|
||||
|
||||
void mpr121_raw(uint8_t addr, uint16_t *raw, int num)
|
||||
{
|
||||
mpr121_read_many16(addr, MPR121_ELECTRODE_FILTERED_DATA_REG, raw, num);
|
||||
}
|
||||
|
||||
static uint8_t mpr121_stop(uint8_t addr)
|
||||
{
|
||||
uint8_t ecr = read_reg(addr, MPR121_ELECTRODE_CONFIG_REG);
|
||||
@ -165,7 +174,7 @@ static uint8_t mpr121_resume(uint8_t addr, uint8_t ecr)
|
||||
write_reg(addr, MPR121_ELECTRODE_CONFIG_REG, ecr);
|
||||
}
|
||||
|
||||
void mpr121_filter(uint8_t addr, uint8_t ffi, uint8_t sfi)
|
||||
void mpr121_filter(uint8_t addr, uint8_t ffi, uint8_t sfi, uint8_t esi)
|
||||
{
|
||||
uint8_t ecr = mpr121_stop(addr);
|
||||
|
||||
@ -174,7 +183,8 @@ void mpr121_filter(uint8_t addr, uint8_t ffi, uint8_t sfi)
|
||||
uint8_t acc = read_reg(addr, MPR121_AUTOCONFIG_CONTROL_0_REG);
|
||||
write_reg(addr, MPR121_AUTOCONFIG_CONTROL_0_REG, (acc & 0x3f) | ffi << 6);
|
||||
uint8_t fcr = read_reg(addr, MPR121_FILTER_CONFIG_REG);
|
||||
write_reg(addr, MPR121_FILTER_CONFIG_REG, (fcr & 0xe7) | (sfi & 3) << 3);
|
||||
write_reg(addr, MPR121_FILTER_CONFIG_REG,
|
||||
(fcr & 0xe0) | ((sfi & 3) << 3) | esi);
|
||||
|
||||
mpr121_resume(addr, ecr);
|
||||
}
|
||||
|
@ -10,8 +10,8 @@
|
||||
void mpr121_init(uint8_t addr);
|
||||
|
||||
uint16_t mpr121_touched(uint8_t addr);
|
||||
|
||||
void mpr121_filter(uint8_t addr, uint8_t ffi, uint8_t sfi);
|
||||
void mpr121_raw(uint8_t addr, uint16_t *raw, int num);
|
||||
void mpr121_filter(uint8_t addr, uint8_t ffi, uint8_t sfi, uint8_t esi);
|
||||
void mpr121_sense(uint8_t addr, int8_t sense, int8_t *sense_keys);
|
||||
void mpr121_debounce(uint8_t addr, uint8_t touch, uint8_t release);
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
static uint32_t rgb_buf[47]; // 16(Keys) + 15(Gaps) + 16(maximum ToF indicators)
|
||||
static uint32_t rgb_buf[20];
|
||||
|
||||
#define _MAP_LED(x) _MAKE_MAPPER(x)
|
||||
#define _MAKE_MAPPER(x) MAP_LED_##x
|
||||
@ -52,6 +52,37 @@ uint32_t rgb32(uint32_t r, uint32_t g, uint32_t b, bool gamma_fix)
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t rgb32_from_hsv(uint8_t h, uint8_t s, uint8_t v)
|
||||
{
|
||||
uint32_t region, remainder, p, q, t;
|
||||
|
||||
if (s == 0) {
|
||||
return v << 16 | v << 8 | v;
|
||||
}
|
||||
|
||||
region = h / 43;
|
||||
remainder = (h % 43) * 6;
|
||||
|
||||
p = (v * (255 - s)) >> 8;
|
||||
q = (v * (255 - ((s * remainder) >> 8))) >> 8;
|
||||
t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8;
|
||||
|
||||
switch (region) {
|
||||
case 0:
|
||||
return v << 16 | t << 8 | p;
|
||||
case 1:
|
||||
return q << 16 | v << 8 | p;
|
||||
case 2:
|
||||
return p << 16 | v << 8 | t;
|
||||
case 3:
|
||||
return p << 16 | q << 8 | v;
|
||||
case 4:
|
||||
return t << 16 | p << 8 | v;
|
||||
default:
|
||||
return v << 16 | p << 8 | q;
|
||||
}
|
||||
}
|
||||
|
||||
static void drive_led()
|
||||
{
|
||||
static uint64_t last = 0;
|
||||
@ -61,10 +92,7 @@ static void drive_led()
|
||||
}
|
||||
last = now;
|
||||
|
||||
for (int i = 30; i >= 0; i--) {
|
||||
pio_sm_put_blocking(pio0, 0, rgb_buf[i] << 8u);
|
||||
}
|
||||
for (int i = 31; i < ARRAY_SIZE(rgb_buf); i++) {
|
||||
for (int i = 0; i < ARRAY_SIZE(rgb_buf); i++) {
|
||||
pio_sm_put_blocking(pio0, 0, rgb_buf[i] << 8u);
|
||||
}
|
||||
}
|
||||
@ -80,28 +108,25 @@ void rgb_set_colors(const uint32_t *colors, unsigned index, size_t num)
|
||||
memcpy(&rgb_buf[index], colors, num * sizeof(*colors));
|
||||
}
|
||||
|
||||
static inline uint32_t apply_level(uint32_t color)
|
||||
{
|
||||
unsigned r = (color >> 16) & 0xff;
|
||||
unsigned g = (color >> 8) & 0xff;
|
||||
unsigned b = color & 0xff;
|
||||
|
||||
r = r * mai_cfg->style.level / 255;
|
||||
g = g * mai_cfg->style.level / 255;
|
||||
b = b * mai_cfg->style.level / 255;
|
||||
|
||||
return r << 16 | g << 8 | b;
|
||||
}
|
||||
|
||||
void rgb_set_color(unsigned index, uint32_t color)
|
||||
{
|
||||
if (index >= ARRAY_SIZE(rgb_buf)) {
|
||||
return;
|
||||
}
|
||||
rgb_buf[index] = color;
|
||||
}
|
||||
|
||||
void rgb_key_color(unsigned index, uint32_t color)
|
||||
{
|
||||
if (index > 16) {
|
||||
return;
|
||||
}
|
||||
rgb_buf[index * 2] = color;
|
||||
}
|
||||
|
||||
void rgb_gap_color(unsigned index, uint32_t color)
|
||||
{
|
||||
if (index > 15) {
|
||||
return;
|
||||
}
|
||||
rgb_buf[index * 2 + 1] = color;
|
||||
rgb_buf[index] = apply_level(color);
|
||||
}
|
||||
|
||||
void rgb_set_brg(unsigned index, const uint8_t *brg_array, size_t num)
|
||||
@ -116,11 +141,10 @@ void rgb_set_brg(unsigned index, const uint8_t *brg_array, size_t num)
|
||||
uint8_t b = brg_array[i * 3 + 0];
|
||||
uint8_t r = brg_array[i * 3 + 1];
|
||||
uint8_t g = brg_array[i * 3 + 2];
|
||||
rgb_buf[index + i] = rgb32(r, g, b, false);
|
||||
rgb_buf[index + i] = apply_level(rgb32(r, g, b, false));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void rgb_init()
|
||||
{
|
||||
uint pio0_offset = pio_add_program(pio0, &ws2812_program);
|
||||
@ -133,3 +157,170 @@ void rgb_update()
|
||||
{
|
||||
drive_led();
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
|
||||
#if defined(__AVR_ATmega32U4__) || defined(ARDUINO_SAMD_ZERO)
|
||||
#pragma message "当前的开发板是 ATmega32U4 或 SAMD_ZERO"
|
||||
#define SerialDevice SerialUSB
|
||||
#define LED_PIN 13
|
||||
|
||||
#elif defined(ARDUINO_ESP8266_NODEMCU_ESP12E)
|
||||
#pragma message "当前的开发板是 NODEMCU_ESP12E"
|
||||
#define SerialDevice Serial
|
||||
#define LED_PIN D5
|
||||
|
||||
#elif defined(ARDUINO_NodeMCU_32S)
|
||||
#pragma message "当前的开发板是 NodeMCU_32S"
|
||||
#define SerialDevice Serial
|
||||
#define LED_PIN 13
|
||||
|
||||
|
||||
#else
|
||||
#error "未经测试的开发板,请检查串口和阵脚定义"
|
||||
#endif
|
||||
|
||||
#include "FastLED.h"
|
||||
#define NUM_LEDS 11
|
||||
CRGBArray<NUM_LEDS> leds;
|
||||
|
||||
|
||||
enum {
|
||||
LedGs8Bit = 0x31,//49
|
||||
LedGs8BitMulti = 0x32,//50
|
||||
LedGs8BitMultiFade = 0x33,//51
|
||||
LedFet = 0x39,//57
|
||||
LedGsUpdate = 0x3C,//60
|
||||
LedDirect = 0x82,
|
||||
};
|
||||
|
||||
typedef union {
|
||||
uint8_t base[64];
|
||||
struct {
|
||||
struct {
|
||||
uint8_t dstNodeID;
|
||||
uint8_t srcNodeID;
|
||||
uint8_t length;
|
||||
uint8_t cmd;
|
||||
};
|
||||
union {
|
||||
struct { //39
|
||||
uint8_t color[11][3];//CRGB
|
||||
};
|
||||
struct { //9
|
||||
uint8_t BodyLed;
|
||||
uint8_t ExtLed;
|
||||
uint8_t SideLed;
|
||||
};
|
||||
struct { //LedGs8Bit
|
||||
uint8_t index;
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
};
|
||||
struct { //LedGs8BitMulti,LedGs8BitMultiFade
|
||||
uint8_t start;
|
||||
uint8_t end;//length
|
||||
uint8_t skip;
|
||||
uint8_t mr;
|
||||
uint8_t mg;
|
||||
uint8_t mb;
|
||||
uint8_t speed;
|
||||
};
|
||||
};
|
||||
};
|
||||
} Packet;
|
||||
|
||||
static Packet req;
|
||||
|
||||
static uint8_t len, r, checksum;
|
||||
static bool escape = false;
|
||||
|
||||
static uint8_t packet_read() {
|
||||
while (SerialDevice.available()) {
|
||||
r = SerialDevice.read();
|
||||
if (r == 0xE0) {
|
||||
len = 0;
|
||||
checksum = 0;
|
||||
continue;
|
||||
}
|
||||
if (r == 0xD0) {
|
||||
escape = true;
|
||||
continue;
|
||||
}
|
||||
if (escape) {
|
||||
r++;
|
||||
escape = false;
|
||||
}
|
||||
|
||||
if (len - 3 == req.length && checksum == r) {
|
||||
return req.cmd;
|
||||
}
|
||||
req.base[len++] = r;
|
||||
checksum += r;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
|
||||
FastLED.setBrightness(30);
|
||||
FastLED.clear();
|
||||
SerialDevice.begin(115200);
|
||||
leds(0, 7) = 0xFFFFFF;
|
||||
FastLED.delay(1000);
|
||||
}
|
||||
|
||||
unsigned long fade_start, fade_end, progress;
|
||||
uint8_t led_start, led_end, fade_tag;
|
||||
CRGB fade_prev, fade_taget;
|
||||
|
||||
void loop() {
|
||||
switch (packet_read()) {
|
||||
case LedGs8Bit:
|
||||
leds[req.index] = CRGB(req.r, req.g, req.b);
|
||||
break;
|
||||
|
||||
case LedGs8BitMulti:
|
||||
if (req.end == 0x20) {
|
||||
req.end = NUM_LEDS;
|
||||
}
|
||||
leds(req.start, req.end - 1) = CRGB(req.mr, req.mg, req.mb);
|
||||
fade_prev = CRGB(req.mr, req.mg, req.mb);
|
||||
fade_tag = 0;
|
||||
break;
|
||||
|
||||
case LedGs8BitMultiFade:
|
||||
fade_taget = CRGB(req.mr, req.mg, req.mb);
|
||||
fade_start = millis();
|
||||
fade_end = fade_start + (4095 / req.speed * 8);
|
||||
led_start = req.start;
|
||||
led_end = req.end - 1;
|
||||
fade_tag = 1;
|
||||
break;
|
||||
|
||||
case LedFet://框体灯,只有白色,值代表亮度,会多次发送实现渐变,需要立刻刷新
|
||||
leds[8] = blend(0x000000, 0xFFFFFF, req.BodyLed);
|
||||
leds[9] = blend(0x000000, 0xFFFFFF, req.ExtLed);//same as BodyLed
|
||||
leds[10] = blend(0x000000, 0xFFFFFF, req.SideLed);//00 or FF
|
||||
FastLED.show();
|
||||
break;
|
||||
|
||||
case LedGsUpdate://提交灯光数据
|
||||
FastLED.show();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!fade_tag)return;
|
||||
if (millis() > fade_end) {
|
||||
progress = 255;
|
||||
fade_tag = 0;
|
||||
} else {
|
||||
progress = map(millis(), fade_start, fade_end, 0, 255);
|
||||
}
|
||||
leds(led_start, led_end) = blend(fade_prev, fade_taget, progress);
|
||||
FastLED.show();
|
||||
}
|
||||
|
||||
#endif
|
@ -16,11 +16,10 @@ void rgb_init();
|
||||
void rgb_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 rgb_set_colors(const uint32_t *colors, unsigned index, size_t num);
|
||||
void rgb_set_color(unsigned index, uint32_t color);
|
||||
void rgb_key_color(unsigned index, uint32_t color);
|
||||
void rgb_gap_color(unsigned index, uint32_t color);
|
||||
|
||||
/* num of the rgb leds, num*3 bytes in the array */
|
||||
void rgb_set_brg(unsigned index, const uint8_t *brg_array, size_t num);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Mai Pico Silder Keys
|
||||
* Chu Pico Silder Keys
|
||||
* WHowe <github.com/whowechina>
|
||||
*
|
||||
* MPR121 CapSense based Keys
|
||||
@ -22,11 +22,9 @@
|
||||
|
||||
#define MPR121_ADDR 0x5A
|
||||
|
||||
static uint16_t baseline[36];
|
||||
static int16_t error[36];
|
||||
static uint16_t readout[36];
|
||||
static bool touched[36];
|
||||
static uint16_t touch[3];
|
||||
static unsigned touch_counts[36];
|
||||
|
||||
void touch_init()
|
||||
{
|
||||
@ -44,26 +42,61 @@ void touch_init()
|
||||
|
||||
void touch_update()
|
||||
{
|
||||
static uint16_t last_touched[3];
|
||||
|
||||
touch[0] = mpr121_touched(MPR121_ADDR);
|
||||
touch[1] = mpr121_touched(MPR121_ADDR + 1);
|
||||
touch[2] = mpr121_touched(MPR121_ADDR + 2);
|
||||
|
||||
for (int m = 0; m < 3; m++) {
|
||||
uint16_t just_touched = touch[m] & ~last_touched[m];
|
||||
last_touched[m] = touch[m];
|
||||
for (int i = 0; i < 12; i++) {
|
||||
if (just_touched & (1 << i)) {
|
||||
touch_counts[m * 12 + i]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const uint16_t *touch_raw()
|
||||
{
|
||||
mpr121_raw(MPR121_ADDR, readout, 12);
|
||||
mpr121_raw(MPR121_ADDR + 1, readout + 12, 12);
|
||||
mpr121_raw(MPR121_ADDR + 2, readout + 24, 12);
|
||||
return readout;
|
||||
}
|
||||
|
||||
bool touch_touched(unsigned key)
|
||||
{
|
||||
if (key >= 32) {
|
||||
if (key >= 34) {
|
||||
return 0;
|
||||
}
|
||||
return touch[key / 12] & (1 << (key % 12));
|
||||
}
|
||||
|
||||
unsigned touch_count(unsigned key)
|
||||
{
|
||||
if (key >= 34) {
|
||||
return 0;
|
||||
}
|
||||
return touch_counts[key];
|
||||
}
|
||||
|
||||
void touch_reset_stat()
|
||||
{
|
||||
memset(touch_counts, 0, sizeof(touch_counts));
|
||||
}
|
||||
|
||||
void touch_update_config()
|
||||
{
|
||||
for (int m = 0; m < 3; m++) {
|
||||
mpr121_debounce(MPR121_ADDR + m, mai_cfg->sense.debounce_touch,
|
||||
mai_cfg->sense.debounce_release);
|
||||
mpr121_sense(MPR121_ADDR + m, mai_cfg->sense.global, mai_cfg->sense.keys + m * 12);
|
||||
mpr121_filter(MPR121_ADDR + m, mai_cfg->sense.filter & 0x0f,
|
||||
(mai_cfg->sense.filter >> 4) & 0x0f);
|
||||
mpr121_sense(MPR121_ADDR + m, mai_cfg->sense.global,
|
||||
mai_cfg->sense.keys + m * 12);
|
||||
mpr121_filter(MPR121_ADDR + m, mai_cfg->sense.filter >> 6,
|
||||
(mai_cfg->sense.filter >> 4) & 0x03,
|
||||
mai_cfg->sense.filter & 0x07);
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
/*
|
||||
* Mai Pico Touch Keys
|
||||
* Chu Pico Silder Keys
|
||||
* WHowe <github.com/whowechina>
|
||||
*/
|
||||
|
||||
#ifndef TOUCH_H
|
||||
#define TOUCH_H
|
||||
#ifndef Silder_H
|
||||
#define Silder_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
@ -12,6 +12,10 @@
|
||||
void touch_init();
|
||||
void touch_update();
|
||||
bool touch_touched(unsigned key);
|
||||
const uint16_t *touch_raw();
|
||||
void touch_update_config();
|
||||
unsigned touch_count(unsigned key);
|
||||
void touch_reset_stat();
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -97,7 +97,7 @@ extern "C" {
|
||||
|
||||
//------------- CLASS -------------//
|
||||
#define CFG_TUD_HID 3
|
||||
#define CFG_TUD_CDC 1
|
||||
#define CFG_TUD_CDC 3
|
||||
#define CFG_TUD_MSC 0
|
||||
#define CFG_TUD_MIDI 0
|
||||
#define CFG_TUD_VENDOR 0
|
||||
@ -111,11 +111,11 @@ extern "C" {
|
||||
#define CFG_TUD_HID_EP_BUFSIZE 64
|
||||
|
||||
// CDC FIFO size of TX and RX
|
||||
#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
|
||||
#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
|
||||
#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 128)
|
||||
#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 128)
|
||||
|
||||
// CDC Endpoint transfer buffer size, more is faster
|
||||
#define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
|
||||
#define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 128)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -75,20 +75,20 @@ uint8_t const* tud_descriptor_device_cb(void) {
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
uint8_t const desc_hid_report_joy[] = {
|
||||
MAIPICO_REPORT_DESC_JOYSTICK,
|
||||
CHUPICO_REPORT_DESC_JOYSTICK,
|
||||
};
|
||||
|
||||
uint8_t const desc_hid_report_led[] = {
|
||||
MAIPICO_LED_HEADER,
|
||||
MAIPICO_REPORT_DESC_LED_touch_16,
|
||||
MAIPICO_REPORT_DESC_LED_touch_15,
|
||||
MAIPICO_REPORT_DESC_LED_TOWER_6,
|
||||
MAIPICO_REPORT_DESC_LED_COMPRESSED,
|
||||
MAIPICO_LED_FOOTER
|
||||
CHUPICO_LED_HEADER,
|
||||
CHUPICO_REPORT_DESC_LED_TOUCH_16,
|
||||
CHUPICO_REPORT_DESC_LED_TOUCH_15,
|
||||
CHUPICO_REPORT_DESC_LED_TOWER_6,
|
||||
CHUPICO_REPORT_DESC_LED_COMPRESSED,
|
||||
CHUPICO_LED_FOOTER
|
||||
};
|
||||
|
||||
uint8_t const desc_hid_report_nkro[] = {
|
||||
MAIPICO_REPORT_DESC_NKRO,
|
||||
CHUPICO_REPORT_DESC_NKRO,
|
||||
};
|
||||
|
||||
// Invoked when received GET HID REPORT DESCRIPTOR
|
||||
@ -111,9 +111,13 @@ uint8_t const* tud_hid_descriptor_report_cb(uint8_t itf)
|
||||
// Configuration Descriptor
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
enum { ITF_NUM_JOY, ITF_NUM_LED, ITF_NUM_NKRO, ITF_NUM_CDC, ITF_NUM_CDC_DATA, ITF_NUM_TOTAL };
|
||||
enum { ITF_NUM_JOY, ITF_NUM_LED, ITF_NUM_NKRO,
|
||||
ITF_NUM_CDC, ITF_NUM_CDC_DATA,
|
||||
ITF_NUM_CDC_TOUCH, ITF_NUM_CDC_DATA_TOUCH,
|
||||
ITF_NUM_CDC_LED, ITF_NUM_CDC_DATA_LED,
|
||||
ITF_NUM_TOTAL };
|
||||
|
||||
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_DESC_LEN * 3 + TUD_CDC_DESC_LEN)
|
||||
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_DESC_LEN * 3 + TUD_CDC_DESC_LEN * 3)
|
||||
|
||||
#define EPNUM_JOY 0x84
|
||||
#define EPNUM_LED 0x85
|
||||
@ -121,6 +125,12 @@ enum { ITF_NUM_JOY, ITF_NUM_LED, ITF_NUM_NKRO, ITF_NUM_CDC, ITF_NUM_CDC_DATA, IT
|
||||
#define EPNUM_CDC_NOTIF 0x81
|
||||
#define EPNUM_CDC_OUT 0x02
|
||||
#define EPNUM_CDC_IN 0x82
|
||||
#define EPNUM_CDC_TOUCH_NOTIF 0x87
|
||||
#define EPNUM_CDC_TOUCH_OUT 0x03
|
||||
#define EPNUM_CDC_TOUCH_IN 0x88
|
||||
#define EPNUM_CDC_LED_NOTIF 0x89
|
||||
#define EPNUM_CDC_LED_OUT 0x04
|
||||
#define EPNUM_CDC_LED_IN 0x8a
|
||||
|
||||
uint8_t const desc_configuration_joy[] = {
|
||||
// Config number, interface count, string index, total length, attribute,
|
||||
@ -143,7 +153,13 @@ uint8_t const desc_configuration_joy[] = {
|
||||
CFG_TUD_HID_EP_BUFSIZE, 1),
|
||||
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 7, EPNUM_CDC_NOTIF,
|
||||
8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64)
|
||||
8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
|
||||
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_TOUCH, 8, EPNUM_CDC_TOUCH_NOTIF,
|
||||
8, EPNUM_CDC_TOUCH_OUT, EPNUM_CDC_TOUCH_IN, 64),
|
||||
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_LED, 9, EPNUM_CDC_LED_NOTIF,
|
||||
8, EPNUM_CDC_LED_OUT, EPNUM_CDC_LED_IN, 64)
|
||||
};
|
||||
|
||||
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
||||
@ -167,6 +183,8 @@ const char *string_desc_arr[] = {
|
||||
"Mai Pico LED",
|
||||
"Mai Pico NKRO",
|
||||
"Mai Pico Serial Port",
|
||||
"Mai Pico Touch Serial Port",
|
||||
"Mai Pico LED Serial Port",
|
||||
};
|
||||
|
||||
// Invoked when received GET STRING DESCRIPTOR request
|
||||
|
@ -6,8 +6,8 @@
|
||||
|
||||
enum {
|
||||
REPORT_ID_JOYSTICK = 1,
|
||||
REPORT_ID_LED_touch_16 = 4,
|
||||
REPORT_ID_LED_touch_15 = 5,
|
||||
REPORT_ID_LED_TOUCH_16 = 4,
|
||||
REPORT_ID_LED_TOUCH_15 = 5,
|
||||
REPORT_ID_LED_TOWER_6 = 6,
|
||||
REPORT_ID_LED_COMPRESSED = 11,
|
||||
};
|
||||
@ -22,7 +22,7 @@ enum {
|
||||
|
||||
// Joystick Report Descriptor Template - Based off Drewol/rp2040-gamecon
|
||||
// Button Map | X | Y
|
||||
#define MAIPICO_REPORT_DESC_JOYSTICK \
|
||||
#define CHUPICO_REPORT_DESC_JOYSTICK \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
|
||||
HID_USAGE(HID_USAGE_DESKTOP_JOYSTICK), \
|
||||
HID_COLLECTION(HID_COLLECTION_APPLICATION), \
|
||||
@ -54,18 +54,18 @@ enum {
|
||||
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
|
||||
HID_COLLECTION_END
|
||||
|
||||
#define MAIPICO_LED_HEADER \
|
||||
#define CHUPICO_LED_HEADER \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), HID_USAGE(0x00), \
|
||||
HID_COLLECTION(HID_COLLECTION_APPLICATION), \
|
||||
HID_REPORT_COUNT(1), HID_REPORT_SIZE(8), \
|
||||
HID_INPUT(HID_CONSTANT | HID_VARIABLE | HID_ABSOLUTE)
|
||||
|
||||
#define MAIPICO_LED_FOOTER \
|
||||
#define CHUPICO_LED_FOOTER \
|
||||
HID_COLLECTION_END
|
||||
|
||||
// Slider First 16 LEDs (48 rgb zones, BRG order)
|
||||
#define MAIPICO_REPORT_DESC_LED_touch_16 \
|
||||
HID_REPORT_ID(REPORT_ID_LED_touch_16) \
|
||||
#define CHUPICO_REPORT_DESC_LED_TOUCH_16 \
|
||||
HID_REPORT_ID(REPORT_ID_LED_TOUCH_16) \
|
||||
HID_REPORT_COUNT(48), HID_REPORT_SIZE(8), \
|
||||
HID_LOGICAL_MIN(0x00), HID_LOGICAL_MAX_N(0x00ff, 2), \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_ORDINAL), \
|
||||
@ -74,8 +74,8 @@ enum {
|
||||
HID_OUTPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE)
|
||||
|
||||
// Slider Remaining 15 LEDs (45 rgb zones, BRG order)
|
||||
#define MAIPICO_REPORT_DESC_LED_touch_15 \
|
||||
HID_REPORT_ID(REPORT_ID_LED_touch_15) \
|
||||
#define CHUPICO_REPORT_DESC_LED_TOUCH_15 \
|
||||
HID_REPORT_ID(REPORT_ID_LED_TOUCH_15) \
|
||||
HID_REPORT_COUNT(45), HID_REPORT_SIZE(8), \
|
||||
HID_LOGICAL_MIN(0x00), HID_LOGICAL_MAX_N(0x00ff, 2), \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_ORDINAL), \
|
||||
@ -84,7 +84,7 @@ enum {
|
||||
HID_OUTPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE)
|
||||
|
||||
// Tower LEDs (18 rgb zones, BRG order)
|
||||
#define MAIPICO_REPORT_DESC_LED_TOWER_6 \
|
||||
#define CHUPICO_REPORT_DESC_LED_TOWER_6 \
|
||||
HID_REPORT_ID(REPORT_ID_LED_TOWER_6) \
|
||||
HID_REPORT_COUNT(18), HID_REPORT_SIZE(8), \
|
||||
HID_LOGICAL_MIN(0x00), HID_LOGICAL_MAX_N(0x00ff, 2), \
|
||||
@ -94,7 +94,7 @@ enum {
|
||||
HID_OUTPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE)
|
||||
|
||||
// LEDs Compressed
|
||||
#define MAIPICO_REPORT_DESC_LED_COMPRESSED \
|
||||
#define CHUPICO_REPORT_DESC_LED_COMPRESSED \
|
||||
HID_REPORT_ID(REPORT_ID_LED_COMPRESSED) \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_ORDINAL), \
|
||||
HID_USAGE(0x00), \
|
||||
@ -102,7 +102,7 @@ enum {
|
||||
HID_REPORT_SIZE(8), HID_REPORT_COUNT(63), \
|
||||
HID_FEATURE(HID_DATA | HID_VARIABLE | HID_ABSOLUTE)
|
||||
|
||||
#define MAIPICO_REPORT_DESC_NKRO \
|
||||
#define CHUPICO_REPORT_DESC_NKRO \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
|
||||
HID_USAGE(HID_USAGE_DESKTOP_KEYBOARD), \
|
||||
HID_COLLECTION(HID_COLLECTION_APPLICATION), \
|
||||
|
Loading…
x
Reference in New Issue
Block a user