205 lines
4.9 KiB
C
205 lines
4.9 KiB
C
#include "hid_mixer.h"
|
|
|
|
#include "tusb.h"
|
|
|
|
#include <string.h>
|
|
|
|
static mixer_state_t g_state;
|
|
static int16_t enc1_acc;
|
|
static int16_t enc2_acc;
|
|
static uint8_t flags_acc;
|
|
static uint8_t pot_val;
|
|
static bool pot_dirty;
|
|
static bool need_send;
|
|
|
|
void hid_mixer_init(void) {
|
|
memset(&g_state, 0, sizeof(g_state));
|
|
g_state.ui_dirty = true;
|
|
enc1_acc = 0;
|
|
enc2_acc = 0;
|
|
flags_acc = 0;
|
|
pot_val = 50;
|
|
pot_dirty = true;
|
|
need_send = true;
|
|
}
|
|
|
|
mixer_state_t *hid_mixer_state(void) {
|
|
return &g_state;
|
|
}
|
|
|
|
bool hid_mixer_mounted(void) {
|
|
return tud_mounted() && tud_hid_ready();
|
|
}
|
|
|
|
void hid_mixer_add_enc1(int8_t delta) {
|
|
enc1_acc += delta;
|
|
if (enc1_acc > 127) {
|
|
enc1_acc = 127;
|
|
}
|
|
if (enc1_acc < -127) {
|
|
enc1_acc = -127;
|
|
}
|
|
need_send = true;
|
|
}
|
|
|
|
void hid_mixer_add_enc2(int8_t delta) {
|
|
enc2_acc += delta;
|
|
if (enc2_acc > 127) {
|
|
enc2_acc = 127;
|
|
}
|
|
if (enc2_acc < -127) {
|
|
enc2_acc = -127;
|
|
}
|
|
need_send = true;
|
|
}
|
|
|
|
void hid_mixer_set_e1_sw(bool pressed) {
|
|
if (pressed) {
|
|
flags_acc |= AUSIO_FLAG_E1_SW;
|
|
need_send = true;
|
|
}
|
|
}
|
|
|
|
void hid_mixer_set_e2_sw(bool pressed) {
|
|
if (pressed) {
|
|
flags_acc |= AUSIO_FLAG_E2_SW;
|
|
need_send = true;
|
|
}
|
|
}
|
|
|
|
void hid_mixer_set_pot(uint8_t pot_0_100) {
|
|
if (pot_0_100 > 100) {
|
|
pot_0_100 = 100;
|
|
}
|
|
if (pot_val != pot_0_100) {
|
|
pot_val = pot_0_100;
|
|
pot_dirty = true;
|
|
need_send = true;
|
|
}
|
|
}
|
|
|
|
static void send_input_if_needed(void) {
|
|
if (!need_send && !pot_dirty) {
|
|
return;
|
|
}
|
|
if (!tud_hid_ready()) {
|
|
return;
|
|
}
|
|
|
|
uint8_t report[AUSIO_INPUT_SIZE];
|
|
memset(report, 0, sizeof(report));
|
|
report[0] = AUSIO_REPORT_ID_INPUT;
|
|
report[1] = (uint8_t)(int8_t)enc1_acc;
|
|
report[2] = (uint8_t)(int8_t)enc2_acc;
|
|
report[3] = flags_acc;
|
|
report[4] = pot_val;
|
|
|
|
if (tud_hid_report(AUSIO_REPORT_ID_INPUT, report + 1, AUSIO_INPUT_SIZE - 1)) {
|
|
enc1_acc = 0;
|
|
enc2_acc = 0;
|
|
flags_acc = 0;
|
|
pot_dirty = false;
|
|
need_send = false;
|
|
}
|
|
}
|
|
|
|
void hid_mixer_task(void) {
|
|
tud_task();
|
|
bool alive = tud_mounted();
|
|
if (alive != g_state.host_alive) {
|
|
g_state.host_alive = alive;
|
|
g_state.ui_dirty = true;
|
|
}
|
|
send_input_if_needed();
|
|
}
|
|
|
|
/* TinyUSB callbacks */
|
|
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) {
|
|
(void)itf;
|
|
(void)report_type;
|
|
|
|
/* With report ID, TinyUSB may pass id separately and buffer without id,
|
|
or include id in buffer depending on path. Handle both. */
|
|
const uint8_t *p = buffer;
|
|
uint16_t len = bufsize;
|
|
|
|
if (report_id == 0 && len > 0) {
|
|
report_id = p[0];
|
|
p++;
|
|
len--;
|
|
}
|
|
|
|
if (report_id != AUSIO_REPORT_ID_OUTPUT) {
|
|
return;
|
|
}
|
|
if (len < (AUSIO_HDR_SIZE - 1)) {
|
|
return;
|
|
}
|
|
|
|
/* p[] without report id:
|
|
* count, selected, master, page, n_vis, master_peak, slots... */
|
|
mixer_state_t next = g_state;
|
|
next.session_count = p[0];
|
|
next.selected = p[1];
|
|
next.master_vol = p[2];
|
|
next.page_start = p[3];
|
|
next.n_visible = p[4];
|
|
next.master_peak = p[5];
|
|
if (next.n_visible > AUSIO_MAX_VISIBLE) {
|
|
next.n_visible = AUSIO_MAX_VISIBLE;
|
|
}
|
|
uint16_t off = 6;
|
|
for (uint8_t i = 0; i < next.n_visible; i++) {
|
|
if (off + AUSIO_SLOT_SIZE > len) {
|
|
next.n_visible = i;
|
|
break;
|
|
}
|
|
next.visible[i].vol = p[off];
|
|
next.visible[i].peak = p[off + 1];
|
|
memcpy(next.visible[i].name, &p[off + 2], AUSIO_NAME_CHARS);
|
|
next.visible[i].name[AUSIO_NAME_CHARS] = '\0';
|
|
off = (uint16_t)(off + AUSIO_SLOT_SIZE);
|
|
}
|
|
|
|
bool changed =
|
|
next.session_count != g_state.session_count ||
|
|
next.selected != g_state.selected ||
|
|
next.master_vol != g_state.master_vol ||
|
|
next.master_peak != g_state.master_peak ||
|
|
next.page_start != g_state.page_start ||
|
|
next.n_visible != g_state.n_visible;
|
|
if (!changed) {
|
|
for (uint8_t i = 0; i < next.n_visible; i++) {
|
|
if (next.visible[i].vol != g_state.visible[i].vol ||
|
|
next.visible[i].peak != g_state.visible[i].peak ||
|
|
memcmp(next.visible[i].name, g_state.visible[i].name, AUSIO_NAME_CHARS) != 0) {
|
|
changed = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (changed) {
|
|
next.ui_dirty = true;
|
|
next.host_alive = g_state.host_alive;
|
|
g_state = next;
|
|
}
|
|
}
|
|
|
|
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) {
|
|
(void)itf;
|
|
(void)report_id;
|
|
(void)report_type;
|
|
(void)buffer;
|
|
(void)reqlen;
|
|
return 0;
|
|
}
|
|
|
|
void tud_hid_report_complete_cb(uint8_t itf, uint8_t const *report, uint16_t len) {
|
|
(void)itf;
|
|
(void)report;
|
|
(void)len;
|
|
}
|