mirror of
https://github.com/whowechina/mai_pico.git
synced 2024-11-24 04:00:09 +01:00
Light effects when idle
This commit is contained in:
parent
a28375dd05
commit
bbd2ff3472
Binary file not shown.
@ -1,379 +1,385 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "io.h"
|
||||
#include "tusb.h"
|
||||
#include "usb_descriptors.h"
|
||||
|
||||
#include "touch.h"
|
||||
#include "rgb.h"
|
||||
|
||||
static struct {
|
||||
bool stat;
|
||||
uint64_t last_io_time;
|
||||
int touch_interface;
|
||||
} ctx = { false, 0, 0 };
|
||||
|
||||
typedef union {
|
||||
uint8_t raw[28];
|
||||
struct {
|
||||
uint8_t body;
|
||||
uint8_t ext;
|
||||
uint8_t side;
|
||||
};
|
||||
struct {
|
||||
uint8_t index;
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
};
|
||||
struct {
|
||||
uint8_t start;
|
||||
uint8_t len;
|
||||
uint8_t skip;
|
||||
uint8_t mr;
|
||||
uint8_t mg;
|
||||
uint8_t mb;
|
||||
uint8_t speed;
|
||||
};
|
||||
struct {
|
||||
uint8_t addr;
|
||||
uint8_t data;
|
||||
} eeprom;
|
||||
uint8_t rgb[11][3];
|
||||
} led_data_t;
|
||||
|
||||
typedef union {
|
||||
uint8_t raw[32];
|
||||
struct {
|
||||
struct {
|
||||
uint8_t dst;
|
||||
uint8_t src;
|
||||
uint8_t len;
|
||||
uint8_t status;
|
||||
uint8_t cmd;
|
||||
uint8_t report;
|
||||
} hdr;
|
||||
uint8_t payload[0];
|
||||
};
|
||||
} led_resp_t;
|
||||
|
||||
#define SYNC 0xE0
|
||||
#define ESCAPE 0xD0
|
||||
|
||||
typedef struct {
|
||||
int interface;
|
||||
bool connected;
|
||||
bool in_cmd;
|
||||
bool is_touch;
|
||||
bool escape;
|
||||
union {
|
||||
uint8_t buf[48];
|
||||
struct {
|
||||
struct {
|
||||
uint8_t dst;
|
||||
uint8_t src;
|
||||
uint8_t len;
|
||||
uint8_t cmd;
|
||||
} hdr;
|
||||
led_data_t led;
|
||||
};
|
||||
};
|
||||
uint8_t len;
|
||||
uint8_t checksum;
|
||||
} cdc_t;
|
||||
|
||||
static cdc_t cdc[2] = {
|
||||
{ .interface = 1 },
|
||||
{ .interface = 2 },
|
||||
};
|
||||
|
||||
static void touch_cmd(cdc_t *cdc)
|
||||
{
|
||||
cdc->in_cmd = false;
|
||||
if (cdc->len != 4) {
|
||||
return;
|
||||
}
|
||||
cdc->len = 0;
|
||||
ctx.last_io_time = time_us_64();
|
||||
|
||||
ctx.touch_interface = cdc->interface;
|
||||
|
||||
switch (cdc->buf[2]) {
|
||||
case 'E':
|
||||
printf("Touch RSET\n");
|
||||
break;
|
||||
case 'L':
|
||||
printf("Touch HALT\n");
|
||||
ctx.stat = false;
|
||||
break;
|
||||
case 'A':
|
||||
printf("Touch STAT\n");
|
||||
ctx.stat = true;
|
||||
break;
|
||||
case 'r':
|
||||
//printf("Touch Ratio\n");
|
||||
tud_cdc_n_write_char(cdc->interface, '(');
|
||||
tud_cdc_n_write_char(cdc->interface, cdc->buf[0]); //L,R
|
||||
tud_cdc_n_write_char(cdc->interface, cdc->buf[1]); //sensor
|
||||
tud_cdc_n_write_char(cdc->interface, 'r');
|
||||
tud_cdc_n_write_char(cdc->interface, cdc->buf[3]); // Ratio
|
||||
tud_cdc_n_write_char(cdc->interface, ')');
|
||||
tud_cdc_n_write_flush(cdc->interface);
|
||||
break;
|
||||
case 'k':
|
||||
// printf("Touch Sense\n");
|
||||
tud_cdc_n_write_char(cdc->interface, '(');
|
||||
tud_cdc_n_write_char(cdc->interface, cdc->buf[0]); //L,R
|
||||
tud_cdc_n_write_char(cdc->interface, cdc->buf[1]); //sensor
|
||||
tud_cdc_n_write_char(cdc->interface, 'k');
|
||||
tud_cdc_n_write_char(cdc->interface, cdc->buf[3]); // Ratio
|
||||
tud_cdc_n_write_char(cdc->interface, ')');
|
||||
tud_cdc_n_write_flush(cdc->interface);
|
||||
break;
|
||||
default:
|
||||
printf("Touch CMD Unknown: %*s -> ", 4, cdc->buf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void led_write(cdc_t *cdc, led_resp_t *resp)
|
||||
{
|
||||
tud_cdc_n_write_char(cdc->interface, SYNC); // SYNC
|
||||
|
||||
uint8_t checksum = 0;
|
||||
for (int i = 0; i < resp->hdr.len + 3; i++) {
|
||||
uint8_t c = resp->raw[i];
|
||||
checksum += c;
|
||||
if (c == SYNC || c == ESCAPE) {
|
||||
tud_cdc_n_write_char(cdc->interface, ESCAPE);
|
||||
tud_cdc_n_write_char(cdc->interface, c - 1);
|
||||
} else {
|
||||
tud_cdc_n_write_char(cdc->interface, c);
|
||||
}
|
||||
}
|
||||
tud_cdc_n_write_char(cdc->interface, checksum);
|
||||
tud_cdc_n_write_flush(cdc->interface);
|
||||
}
|
||||
|
||||
static led_resp_t *led_init_resp(cdc_t *cdc, uint8_t payload_len)
|
||||
{
|
||||
static led_resp_t resp;
|
||||
resp.hdr.dst = cdc->hdr.src;
|
||||
resp.hdr.src = cdc->hdr.dst;
|
||||
resp.hdr.len = payload_len + 3;
|
||||
resp.hdr.status = 1;
|
||||
resp.hdr.cmd = cdc->hdr.cmd;
|
||||
resp.hdr.report = 1;
|
||||
return &resp;
|
||||
}
|
||||
|
||||
static void led_ack_ok(cdc_t *cdc)
|
||||
{
|
||||
led_resp_t *resp = led_init_resp(cdc, 0);
|
||||
led_write(cdc, resp);
|
||||
}
|
||||
|
||||
static uint8_t led_ram[256];
|
||||
|
||||
static void led_set_eeprom(cdc_t *cdc)
|
||||
{
|
||||
led_ram[cdc->led.eeprom.addr] = cdc->led.eeprom.data;
|
||||
led_ack_ok(cdc);
|
||||
}
|
||||
|
||||
static void led_get_eeprom(cdc_t *cdc)
|
||||
{
|
||||
led_resp_t *resp = led_init_resp(cdc, 1);
|
||||
resp->payload[0] = led_ram[cdc->led.eeprom.addr];
|
||||
led_write(cdc, resp);
|
||||
}
|
||||
|
||||
static void led_board_info(cdc_t *cdc)
|
||||
{
|
||||
led_resp_t *resp = led_init_resp(cdc, 10);
|
||||
memcpy(resp->payload, "15070-04\xff\x90", 10);
|
||||
led_write(cdc, resp);
|
||||
}
|
||||
|
||||
static void led_board_status(cdc_t *cdc)
|
||||
{
|
||||
led_resp_t *resp = led_init_resp(cdc, 4);
|
||||
memcpy(resp->payload, "\x00\x00\x00\x00", 4);
|
||||
led_write(cdc, resp);
|
||||
}
|
||||
|
||||
static void led_proto_ver(cdc_t *cdc)
|
||||
{
|
||||
led_resp_t *resp = led_init_resp(cdc, 3);
|
||||
memcpy(resp->payload, "\x01\x00\x00", 3);
|
||||
led_write(cdc, resp);
|
||||
}
|
||||
|
||||
static void led_cmd(cdc_t *cdc)
|
||||
{
|
||||
cdc->in_cmd = false;
|
||||
cdc->len = 0;
|
||||
ctx.last_io_time = time_us_64();
|
||||
|
||||
uint32_t color;
|
||||
switch (cdc->hdr.cmd) {
|
||||
case 0x10:
|
||||
printf("LED RSET\n");
|
||||
for (int i = 0; i < 8; i++) {
|
||||
rgb_set_button(i, 0, 0);
|
||||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
rgb_set_cab(i, 0);
|
||||
}
|
||||
break;
|
||||
case 0x31:
|
||||
color = rgb32(cdc->led.r, cdc->led.g, cdc->led.b, false);
|
||||
//printf("LED %d:1 %06x\n", cdc->led.index, color);
|
||||
rgb_set_button(cdc->led.index, color, 0);
|
||||
break;
|
||||
case 0x32:
|
||||
color = rgb32(cdc->led.mr, cdc->led.mg, cdc->led.mb, false);
|
||||
//printf("LED %d:%d %06x\n", cdc->led.start, cdc->led.len, color, cdc->led.mb);
|
||||
for (int i = 0; i < cdc->led.len; i++) {
|
||||
rgb_set_button(i + cdc->led.start, color, 0);
|
||||
}
|
||||
break;
|
||||
case 0x33:
|
||||
color = rgb32(cdc->led.mr, cdc->led.mg, cdc->led.mb, false);
|
||||
//printf("LED %d:%d %06x %d\n", cdc->led.start, cdc->led.len, color, cdc->led.speed);
|
||||
for (int i = 0; i < cdc->led.len; i++) {
|
||||
rgb_set_button(i + cdc->led.start, color, cdc->led.speed);
|
||||
}
|
||||
break;
|
||||
case 0x39:
|
||||
//printf("LED Fet\n");
|
||||
rgb_set_cab(0, gray32(cdc->led.body, false));
|
||||
rgb_set_cab(1, gray32(cdc->led.ext, false));
|
||||
rgb_set_cab(2, gray32(cdc->led.side, false));
|
||||
break;
|
||||
|
||||
case 0x7b:
|
||||
led_set_eeprom(cdc);
|
||||
return;
|
||||
case 0x7c:
|
||||
led_get_eeprom(cdc);
|
||||
return;
|
||||
case 0xf0:
|
||||
led_board_info(cdc);
|
||||
return;
|
||||
case 0xf1:
|
||||
led_board_status(cdc);
|
||||
return;
|
||||
case 0xf3:
|
||||
led_proto_ver(cdc);
|
||||
return;
|
||||
|
||||
default:
|
||||
printf("Ignoring LED Cmd %02x\n", cdc->hdr.cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
led_ack_ok(cdc);
|
||||
}
|
||||
|
||||
static inline void assemble_cmd(cdc_t *cdc, uint8_t c)
|
||||
{
|
||||
if (c == SYNC) {
|
||||
cdc->len = 0;
|
||||
cdc->in_cmd = true;
|
||||
cdc->is_touch = false;
|
||||
cdc->escape = false;
|
||||
cdc->checksum = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!cdc->in_cmd || cdc->is_touch) && (c == '{')) {
|
||||
cdc->len = 0;
|
||||
cdc->in_cmd = true;
|
||||
cdc->is_touch = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (cdc->is_touch) {
|
||||
// Touch cmd
|
||||
if (c == '}') {
|
||||
touch_cmd(cdc);
|
||||
} else if (cdc->len < sizeof(cdc->buf)) {
|
||||
cdc->buf[cdc->len] = c;
|
||||
cdc->len++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// LED cmd
|
||||
if (c == ESCAPE) {
|
||||
cdc->escape = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (cdc->escape) {
|
||||
cdc->escape = false;
|
||||
c++;
|
||||
}
|
||||
|
||||
if ((cdc->len == cdc->hdr.len + 3) && (cdc->checksum == c)) {
|
||||
led_cmd(cdc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cdc->len < sizeof(cdc->buf)) {
|
||||
cdc->buf[cdc->len] = c;
|
||||
cdc->len++;
|
||||
cdc->checksum += c;
|
||||
}
|
||||
}
|
||||
|
||||
static void update_itf(cdc_t *cdc)
|
||||
{
|
||||
cdc->connected = tud_cdc_n_connected(cdc->interface);
|
||||
|
||||
if (tud_cdc_n_available(cdc->interface)) {
|
||||
uint8_t buf[48];
|
||||
uint32_t count = tud_cdc_n_read(cdc->interface, buf, sizeof(buf));
|
||||
for (int i = 0; i < count; i++) {
|
||||
assemble_cmd(cdc, buf[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void send_touch()
|
||||
{
|
||||
if ((ctx.touch_interface == 0) | (!ctx.stat)) {
|
||||
return;
|
||||
}
|
||||
|
||||
static uint64_t last_sent_time = 0;
|
||||
uint64_t now = time_us_64();
|
||||
if (now - last_sent_time < 1000) {
|
||||
return;
|
||||
}
|
||||
last_sent_time = now;
|
||||
|
||||
|
||||
uint8_t report[9] = "(\0\0\0\0\0\0\0)";
|
||||
uint64_t touch = touch_touchmap();
|
||||
for (int i = 0; i < 7; i++) {
|
||||
report[i + 1] = touch & 0x1f;
|
||||
touch >>= 5;
|
||||
}
|
||||
tud_cdc_n_write(ctx.touch_interface, report, sizeof(report));
|
||||
tud_cdc_n_write_flush(ctx.touch_interface);
|
||||
}
|
||||
|
||||
void io_update()
|
||||
{
|
||||
update_itf(cdc);
|
||||
update_itf(cdc + 1);
|
||||
send_touch();
|
||||
}
|
||||
|
||||
uint64_t io_last_io_time()
|
||||
{
|
||||
return ctx.last_io_time;
|
||||
}
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "io.h"
|
||||
#include "tusb.h"
|
||||
#include "usb_descriptors.h"
|
||||
|
||||
#include "touch.h"
|
||||
#include "rgb.h"
|
||||
|
||||
#define IO_TIMEOUT_SEC 10
|
||||
|
||||
static struct {
|
||||
bool stat;
|
||||
uint64_t last_io_time;
|
||||
int touch_interface;
|
||||
} ctx = { false, 0, 0 };
|
||||
|
||||
typedef union {
|
||||
uint8_t raw[28];
|
||||
struct {
|
||||
uint8_t body;
|
||||
uint8_t ext;
|
||||
uint8_t side;
|
||||
};
|
||||
struct {
|
||||
uint8_t index;
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
};
|
||||
struct {
|
||||
uint8_t start;
|
||||
uint8_t len;
|
||||
uint8_t skip;
|
||||
uint8_t mr;
|
||||
uint8_t mg;
|
||||
uint8_t mb;
|
||||
uint8_t speed;
|
||||
};
|
||||
struct {
|
||||
uint8_t addr;
|
||||
uint8_t data;
|
||||
} eeprom;
|
||||
uint8_t rgb[11][3];
|
||||
} led_data_t;
|
||||
|
||||
typedef union {
|
||||
uint8_t raw[32];
|
||||
struct {
|
||||
struct {
|
||||
uint8_t dst;
|
||||
uint8_t src;
|
||||
uint8_t len;
|
||||
uint8_t status;
|
||||
uint8_t cmd;
|
||||
uint8_t report;
|
||||
} hdr;
|
||||
uint8_t payload[0];
|
||||
};
|
||||
} led_resp_t;
|
||||
|
||||
#define SYNC 0xE0
|
||||
#define ESCAPE 0xD0
|
||||
|
||||
typedef struct {
|
||||
int interface;
|
||||
bool connected;
|
||||
bool in_cmd;
|
||||
bool is_touch;
|
||||
bool escape;
|
||||
union {
|
||||
uint8_t buf[48];
|
||||
struct {
|
||||
struct {
|
||||
uint8_t dst;
|
||||
uint8_t src;
|
||||
uint8_t len;
|
||||
uint8_t cmd;
|
||||
} hdr;
|
||||
led_data_t led;
|
||||
};
|
||||
};
|
||||
uint8_t len;
|
||||
uint8_t checksum;
|
||||
} cdc_t;
|
||||
|
||||
static cdc_t cdc[2] = {
|
||||
{ .interface = 1 },
|
||||
{ .interface = 2 },
|
||||
};
|
||||
|
||||
static void touch_cmd(cdc_t *cdc)
|
||||
{
|
||||
cdc->in_cmd = false;
|
||||
if (cdc->len != 4) {
|
||||
return;
|
||||
}
|
||||
cdc->len = 0;
|
||||
ctx.last_io_time = time_us_64();
|
||||
|
||||
ctx.touch_interface = cdc->interface;
|
||||
|
||||
switch (cdc->buf[2]) {
|
||||
case 'E':
|
||||
printf("Touch RSET\n");
|
||||
break;
|
||||
case 'L':
|
||||
printf("Touch HALT\n");
|
||||
ctx.stat = false;
|
||||
break;
|
||||
case 'A':
|
||||
printf("Touch STAT\n");
|
||||
ctx.stat = true;
|
||||
break;
|
||||
case 'r':
|
||||
//printf("Touch Ratio\n");
|
||||
tud_cdc_n_write_char(cdc->interface, '(');
|
||||
tud_cdc_n_write_char(cdc->interface, cdc->buf[0]); //L,R
|
||||
tud_cdc_n_write_char(cdc->interface, cdc->buf[1]); //sensor
|
||||
tud_cdc_n_write_char(cdc->interface, 'r');
|
||||
tud_cdc_n_write_char(cdc->interface, cdc->buf[3]); // Ratio
|
||||
tud_cdc_n_write_char(cdc->interface, ')');
|
||||
tud_cdc_n_write_flush(cdc->interface);
|
||||
break;
|
||||
case 'k':
|
||||
// printf("Touch Sense\n");
|
||||
tud_cdc_n_write_char(cdc->interface, '(');
|
||||
tud_cdc_n_write_char(cdc->interface, cdc->buf[0]); //L,R
|
||||
tud_cdc_n_write_char(cdc->interface, cdc->buf[1]); //sensor
|
||||
tud_cdc_n_write_char(cdc->interface, 'k');
|
||||
tud_cdc_n_write_char(cdc->interface, cdc->buf[3]); // Ratio
|
||||
tud_cdc_n_write_char(cdc->interface, ')');
|
||||
tud_cdc_n_write_flush(cdc->interface);
|
||||
break;
|
||||
default:
|
||||
printf("Touch CMD Unknown: %*s -> ", 4, cdc->buf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void led_write(cdc_t *cdc, led_resp_t *resp)
|
||||
{
|
||||
tud_cdc_n_write_char(cdc->interface, SYNC); // SYNC
|
||||
|
||||
uint8_t checksum = 0;
|
||||
for (int i = 0; i < resp->hdr.len + 3; i++) {
|
||||
uint8_t c = resp->raw[i];
|
||||
checksum += c;
|
||||
if (c == SYNC || c == ESCAPE) {
|
||||
tud_cdc_n_write_char(cdc->interface, ESCAPE);
|
||||
tud_cdc_n_write_char(cdc->interface, c - 1);
|
||||
} else {
|
||||
tud_cdc_n_write_char(cdc->interface, c);
|
||||
}
|
||||
}
|
||||
tud_cdc_n_write_char(cdc->interface, checksum);
|
||||
tud_cdc_n_write_flush(cdc->interface);
|
||||
}
|
||||
|
||||
static led_resp_t *led_init_resp(cdc_t *cdc, uint8_t payload_len)
|
||||
{
|
||||
static led_resp_t resp;
|
||||
resp.hdr.dst = cdc->hdr.src;
|
||||
resp.hdr.src = cdc->hdr.dst;
|
||||
resp.hdr.len = payload_len + 3;
|
||||
resp.hdr.status = 1;
|
||||
resp.hdr.cmd = cdc->hdr.cmd;
|
||||
resp.hdr.report = 1;
|
||||
return &resp;
|
||||
}
|
||||
|
||||
static void led_ack_ok(cdc_t *cdc)
|
||||
{
|
||||
led_resp_t *resp = led_init_resp(cdc, 0);
|
||||
led_write(cdc, resp);
|
||||
}
|
||||
|
||||
static uint8_t led_ram[256];
|
||||
|
||||
static void led_set_eeprom(cdc_t *cdc)
|
||||
{
|
||||
led_ram[cdc->led.eeprom.addr] = cdc->led.eeprom.data;
|
||||
led_ack_ok(cdc);
|
||||
}
|
||||
|
||||
static void led_get_eeprom(cdc_t *cdc)
|
||||
{
|
||||
led_resp_t *resp = led_init_resp(cdc, 1);
|
||||
resp->payload[0] = led_ram[cdc->led.eeprom.addr];
|
||||
led_write(cdc, resp);
|
||||
}
|
||||
|
||||
static void led_board_info(cdc_t *cdc)
|
||||
{
|
||||
led_resp_t *resp = led_init_resp(cdc, 10);
|
||||
memcpy(resp->payload, "15070-04\xff\x90", 10);
|
||||
led_write(cdc, resp);
|
||||
}
|
||||
|
||||
static void led_board_status(cdc_t *cdc)
|
||||
{
|
||||
led_resp_t *resp = led_init_resp(cdc, 4);
|
||||
memcpy(resp->payload, "\x00\x00\x00\x00", 4);
|
||||
led_write(cdc, resp);
|
||||
}
|
||||
|
||||
static void led_proto_ver(cdc_t *cdc)
|
||||
{
|
||||
led_resp_t *resp = led_init_resp(cdc, 3);
|
||||
memcpy(resp->payload, "\x01\x00\x00", 3);
|
||||
led_write(cdc, resp);
|
||||
}
|
||||
|
||||
static void led_cmd(cdc_t *cdc)
|
||||
{
|
||||
cdc->in_cmd = false;
|
||||
cdc->len = 0;
|
||||
ctx.last_io_time = time_us_64();
|
||||
|
||||
uint32_t color;
|
||||
switch (cdc->hdr.cmd) {
|
||||
case 0x10:
|
||||
printf("LED RSET\n");
|
||||
for (int i = 0; i < 8; i++) {
|
||||
rgb_set_button(i, 0, 0);
|
||||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
rgb_set_cab(i, 0);
|
||||
}
|
||||
break;
|
||||
case 0x31:
|
||||
color = rgb32(cdc->led.r, cdc->led.g, cdc->led.b, false);
|
||||
//printf("LED %d:1 %06x\n", cdc->led.index, color);
|
||||
rgb_set_button(cdc->led.index, color, 0);
|
||||
break;
|
||||
case 0x32:
|
||||
color = rgb32(cdc->led.mr, cdc->led.mg, cdc->led.mb, false);
|
||||
//printf("LED %d:%d %06x\n", cdc->led.start, cdc->led.len, color, cdc->led.mb);
|
||||
for (int i = 0; i < cdc->led.len; i++) {
|
||||
rgb_set_button(i + cdc->led.start, color, 0);
|
||||
}
|
||||
break;
|
||||
case 0x33:
|
||||
color = rgb32(cdc->led.mr, cdc->led.mg, cdc->led.mb, false);
|
||||
//printf("LED %d:%d %06x %d\n", cdc->led.start, cdc->led.len, color, cdc->led.speed);
|
||||
for (int i = 0; i < cdc->led.len; i++) {
|
||||
rgb_set_button(i + cdc->led.start, color, cdc->led.speed);
|
||||
}
|
||||
break;
|
||||
case 0x39:
|
||||
//printf("LED Fet\n");
|
||||
rgb_set_cab(0, gray32(cdc->led.body, false));
|
||||
rgb_set_cab(1, gray32(cdc->led.ext, false));
|
||||
rgb_set_cab(2, gray32(cdc->led.side, false));
|
||||
break;
|
||||
|
||||
case 0x7b:
|
||||
led_set_eeprom(cdc);
|
||||
return;
|
||||
case 0x7c:
|
||||
led_get_eeprom(cdc);
|
||||
return;
|
||||
case 0xf0:
|
||||
led_board_info(cdc);
|
||||
return;
|
||||
case 0xf1:
|
||||
led_board_status(cdc);
|
||||
return;
|
||||
case 0xf3:
|
||||
led_proto_ver(cdc);
|
||||
return;
|
||||
|
||||
default:
|
||||
printf("Ignoring LED Cmd %02x\n", cdc->hdr.cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
led_ack_ok(cdc);
|
||||
}
|
||||
|
||||
static inline void assemble_cmd(cdc_t *cdc, uint8_t c)
|
||||
{
|
||||
if (c == SYNC) {
|
||||
cdc->len = 0;
|
||||
cdc->in_cmd = true;
|
||||
cdc->is_touch = false;
|
||||
cdc->escape = false;
|
||||
cdc->checksum = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!cdc->in_cmd || cdc->is_touch) && (c == '{')) {
|
||||
cdc->len = 0;
|
||||
cdc->in_cmd = true;
|
||||
cdc->is_touch = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (cdc->is_touch) {
|
||||
// Touch cmd
|
||||
if (c == '}') {
|
||||
touch_cmd(cdc);
|
||||
} else if (cdc->len < sizeof(cdc->buf)) {
|
||||
cdc->buf[cdc->len] = c;
|
||||
cdc->len++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// LED cmd
|
||||
if (c == ESCAPE) {
|
||||
cdc->escape = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (cdc->escape) {
|
||||
cdc->escape = false;
|
||||
c++;
|
||||
}
|
||||
|
||||
if ((cdc->len == cdc->hdr.len + 3) && (cdc->checksum == c)) {
|
||||
led_cmd(cdc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cdc->len < sizeof(cdc->buf)) {
|
||||
cdc->buf[cdc->len] = c;
|
||||
cdc->len++;
|
||||
cdc->checksum += c;
|
||||
}
|
||||
}
|
||||
|
||||
static void update_itf(cdc_t *cdc)
|
||||
{
|
||||
cdc->connected = tud_cdc_n_connected(cdc->interface);
|
||||
|
||||
if (tud_cdc_n_available(cdc->interface)) {
|
||||
uint8_t buf[48];
|
||||
uint32_t count = tud_cdc_n_read(cdc->interface, buf, sizeof(buf));
|
||||
for (int i = 0; i < count; i++) {
|
||||
assemble_cmd(cdc, buf[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void send_touch()
|
||||
{
|
||||
if ((ctx.touch_interface == 0) | (!ctx.stat)) {
|
||||
return;
|
||||
}
|
||||
|
||||
static uint64_t last_sent_time = 0;
|
||||
uint64_t now = time_us_64();
|
||||
if (now - last_sent_time < 1000) {
|
||||
return;
|
||||
}
|
||||
last_sent_time = now;
|
||||
|
||||
|
||||
uint8_t report[9] = "(\0\0\0\0\0\0\0)";
|
||||
uint64_t touch = touch_touchmap();
|
||||
for (int i = 0; i < 7; i++) {
|
||||
report[i + 1] = touch & 0x1f;
|
||||
touch >>= 5;
|
||||
}
|
||||
tud_cdc_n_write(ctx.touch_interface, report, sizeof(report));
|
||||
tud_cdc_n_write_flush(ctx.touch_interface);
|
||||
}
|
||||
|
||||
void io_update()
|
||||
{
|
||||
update_itf(cdc);
|
||||
update_itf(cdc + 1);
|
||||
send_touch();
|
||||
}
|
||||
|
||||
bool io_is_active()
|
||||
{
|
||||
if (ctx.last_io_time == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return time_us_64() < ctx.last_io_time + IO_TIMEOUT_SEC * 1000000;
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Game I/O
|
||||
* WHowe <github.com/whowechina>
|
||||
*/
|
||||
|
||||
#ifndef IO_H_
|
||||
#define IO_H_
|
||||
|
||||
void io_update();
|
||||
uint64_t io_last_io_time();
|
||||
|
||||
/*
|
||||
* Game I/O
|
||||
* WHowe <github.com/whowechina>
|
||||
*/
|
||||
|
||||
#ifndef IO_H_
|
||||
#define IO_H_
|
||||
|
||||
void io_update();
|
||||
bool io_is_active();
|
||||
|
||||
#endif
|
@ -1,168 +1,173 @@
|
||||
/*
|
||||
* 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 "tusb.h"
|
||||
#include "usb_descriptors.h"
|
||||
|
||||
#include "aime.h"
|
||||
#include "nfc.h"
|
||||
|
||||
#include "board_defs.h"
|
||||
|
||||
#include "touch.h"
|
||||
#include "button.h"
|
||||
#include "rgb.h"
|
||||
|
||||
#include "save.h"
|
||||
#include "config.h"
|
||||
#include "cli.h"
|
||||
#include "commands.h"
|
||||
#include "io.h"
|
||||
#include "hid.h"
|
||||
|
||||
static void run_lights()
|
||||
{
|
||||
uint64_t now = time_us_64();
|
||||
if (io_last_io_time() != 0 && now - io_last_io_time() < 60000000) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t buttons = button_read();
|
||||
for (int i = 0; i < 8; i++) {
|
||||
uint32_t color = mai_cfg->color.key_off;
|
||||
if (buttons & (1 << i)) {
|
||||
color = mai_cfg->color.key_on;
|
||||
}
|
||||
rgb_set_button(i, color, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const int aime_intf = 3;
|
||||
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];
|
||||
uint32_t count = tud_cdc_n_read(aime_intf, buf, sizeof(buf));
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
aime_feed(buf[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
static mutex_t core1_io_lock;
|
||||
static void core1_loop()
|
||||
{
|
||||
while (1) {
|
||||
if (mutex_try_enter(&core1_io_lock, NULL)) {
|
||||
run_lights();
|
||||
rgb_update();
|
||||
mutex_exit(&core1_io_lock);
|
||||
}
|
||||
cli_fps_count(1);
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void core0_loop()
|
||||
{
|
||||
static uint64_t next_frame = 0;
|
||||
|
||||
while(1) {
|
||||
tud_task();
|
||||
io_update();
|
||||
|
||||
cli_run();
|
||||
aime_run();
|
||||
save_loop();
|
||||
cli_fps_count(0);
|
||||
|
||||
sleep_until(next_frame);
|
||||
next_frame = time_us_64() + 1000; // 1KHz
|
||||
|
||||
touch_update();
|
||||
button_update();
|
||||
|
||||
hid_update();
|
||||
}
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
sleep_ms(50);
|
||||
set_sys_clock_khz(150000, true);
|
||||
board_init();
|
||||
|
||||
tusb_init();
|
||||
stdio_init_all();
|
||||
|
||||
config_init();
|
||||
mutex_init(&core1_io_lock);
|
||||
|
||||
save_init(board_id_32() ^ 0xcafe1111, &core1_io_lock);
|
||||
|
||||
touch_init();
|
||||
button_init();
|
||||
rgb_init();
|
||||
|
||||
nfc_attach_i2c(I2C_PORT);
|
||||
nfc_init();
|
||||
aime_init(cdc_aime_putc);
|
||||
aime_set_mode(mai_cfg->aime.mode);
|
||||
aime_virtual_aic(mai_cfg->aime.virtual_aic);
|
||||
|
||||
cli_init("mai_pico>", "\n << Mai Pico Controller >>\n"
|
||||
" https://github.com/whowechina\n\n");
|
||||
commands_init();
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
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)
|
||||
{
|
||||
hid_proc(buffer, 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 "tusb.h"
|
||||
#include "usb_descriptors.h"
|
||||
|
||||
#include "aime.h"
|
||||
#include "nfc.h"
|
||||
|
||||
#include "board_defs.h"
|
||||
|
||||
#include "touch.h"
|
||||
#include "button.h"
|
||||
#include "rgb.h"
|
||||
|
||||
#include "save.h"
|
||||
#include "config.h"
|
||||
#include "cli.h"
|
||||
#include "commands.h"
|
||||
#include "io.h"
|
||||
#include "hid.h"
|
||||
|
||||
static void run_lights()
|
||||
{
|
||||
uint64_t now = time_us_64();
|
||||
if (io_is_active()) {
|
||||
return;
|
||||
}
|
||||
|
||||
static uint16_t loop = 0;
|
||||
loop++;
|
||||
uint16_t buttons = button_read();
|
||||
for (int i = 0; i < 8; i++) {
|
||||
uint8_t phase = (i * 256 + loop) / 8;
|
||||
uint32_t color;
|
||||
if (buttons & (1 << i)) {
|
||||
color = rgb32_from_hsv(phase, 64, 255);
|
||||
} else {
|
||||
color = rgb32_from_hsv(phase, 240, 20);
|
||||
}
|
||||
rgb_set_button(i, color, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const int aime_intf = 3;
|
||||
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];
|
||||
uint32_t count = tud_cdc_n_read(aime_intf, buf, sizeof(buf));
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
aime_feed(buf[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
static mutex_t core1_io_lock;
|
||||
static void core1_loop()
|
||||
{
|
||||
while (1) {
|
||||
if (mutex_try_enter(&core1_io_lock, NULL)) {
|
||||
run_lights();
|
||||
rgb_update();
|
||||
mutex_exit(&core1_io_lock);
|
||||
}
|
||||
cli_fps_count(1);
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void core0_loop()
|
||||
{
|
||||
uint64_t next_frame = time_us_64();
|
||||
|
||||
while(1) {
|
||||
tud_task();
|
||||
io_update();
|
||||
|
||||
cli_run();
|
||||
aime_run();
|
||||
save_loop();
|
||||
cli_fps_count(0);
|
||||
|
||||
sleep_until(next_frame);
|
||||
next_frame += 1000; // 1KHz
|
||||
|
||||
touch_update();
|
||||
button_update();
|
||||
|
||||
hid_update();
|
||||
}
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
sleep_ms(50);
|
||||
set_sys_clock_khz(150000, true);
|
||||
board_init();
|
||||
|
||||
tusb_init();
|
||||
stdio_init_all();
|
||||
|
||||
config_init();
|
||||
mutex_init(&core1_io_lock);
|
||||
|
||||
save_init(board_id_32() ^ 0xcafe1111, &core1_io_lock);
|
||||
|
||||
touch_init();
|
||||
button_init();
|
||||
rgb_init();
|
||||
|
||||
nfc_attach_i2c(I2C_PORT);
|
||||
nfc_init();
|
||||
aime_init(cdc_aime_putc);
|
||||
aime_set_mode(mai_cfg->aime.mode);
|
||||
aime_virtual_aic(mai_cfg->aime.virtual_aic);
|
||||
|
||||
cli_init("mai_pico>", "\n << Mai Pico Controller >>\n"
|
||||
" https://github.com/whowechina\n\n");
|
||||
commands_init();
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
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)
|
||||
{
|
||||
hid_proc(buffer, bufsize);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user