mirror of
https://github.com/whowechina/chu_pico.git
synced 2026-10-10 08:08:37 +03:00
Cleanup headers
This commit is contained in:
+124
-125
@@ -1,125 +1,124 @@
|
||||
/*
|
||||
* Chu Pico Air Sensor
|
||||
* WHowe <github.com/whowechina>
|
||||
*
|
||||
* Use ToF (Sharp GP2Y0E03) to detect air keys
|
||||
*/
|
||||
|
||||
#include "air.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "bsp/board.h"
|
||||
#include "hardware/gpio.h"
|
||||
|
||||
#include "board_defs.h"
|
||||
#include "config.h"
|
||||
|
||||
#include "gp2y0e.h"
|
||||
#include "vl53l0x.h"
|
||||
#include "i2c_hub.h"
|
||||
|
||||
static const uint8_t TOF_LIST[] = TOF_MUX_LIST;
|
||||
static uint8_t tof_model[sizeof(TOF_LIST)];
|
||||
static uint16_t distances[sizeof(TOF_LIST)];
|
||||
|
||||
void air_init()
|
||||
{
|
||||
i2c_init(I2C_PORT, I2C_FREQ);
|
||||
gpio_set_function(I2C_SDA, GPIO_FUNC_I2C);
|
||||
gpio_set_function(I2C_SCL, GPIO_FUNC_I2C);
|
||||
gpio_pull_up(I2C_SDA);
|
||||
gpio_pull_up(I2C_SCL);
|
||||
|
||||
i2c_hub_init();
|
||||
vl53l0x_init(I2C_PORT, 0);
|
||||
|
||||
for (int i = 0; i < sizeof(TOF_LIST); i++) {
|
||||
i2c_select(I2C_PORT, 1 << TOF_LIST[i]);
|
||||
if (vl53l0x_is_present()) {
|
||||
tof_model[i] = 1;
|
||||
} else if (gp2y0e_is_present(I2C_PORT)) {
|
||||
tof_model[i] = 2;
|
||||
} else {
|
||||
tof_model[i] = 0;
|
||||
}
|
||||
if (tof_model[i] == 1) {
|
||||
vl53l0x_init_tof(i);
|
||||
vl53l0x_start_continuous(i);
|
||||
} else if (tof_model[i] == 2) {
|
||||
gp2y03_init(I2C_PORT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t air_num()
|
||||
{
|
||||
return sizeof(TOF_LIST);
|
||||
}
|
||||
|
||||
static inline uint8_t air_bits(int dist, int offset)
|
||||
{
|
||||
if ((dist < offset) || (dist == 4095)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pitch = chu_cfg->tof.pitch * 10;
|
||||
int index = (dist - offset) / pitch;
|
||||
if (index >= 6) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1 << index;
|
||||
}
|
||||
|
||||
uint8_t air_bitmap()
|
||||
{
|
||||
int offset = chu_cfg->tof.offset * 10;
|
||||
int pitch = chu_cfg->tof.pitch * 10;
|
||||
uint8_t bitmap = 0;
|
||||
for (int i = 0; i < sizeof(TOF_LIST); i++) {
|
||||
bitmap |= air_bits(distances[i], offset) |
|
||||
air_bits(distances[i], offset + pitch);
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
unsigned air_value(uint8_t index)
|
||||
{
|
||||
if (index >= sizeof(TOF_LIST)) {
|
||||
return 0;
|
||||
}
|
||||
int offset = chu_cfg->tof.offset * 10;
|
||||
int pitch = chu_cfg->tof.pitch * 10;
|
||||
uint8_t bitmap = air_bits(distances[index], offset) |
|
||||
air_bits(distances[index], offset + pitch);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (bitmap & (1 << i)) {
|
||||
return i + 1; // lowest detected position
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void air_update()
|
||||
{
|
||||
for (int i = 0; i < sizeof(TOF_LIST); i++) {
|
||||
i2c_select(I2C_PORT, 1 << TOF_LIST[i]);
|
||||
if (tof_model[i] == 1) {
|
||||
distances[i] = readRangeContinuousMillimeters(i) * 10;
|
||||
} else if (tof_model[i] == 2) {
|
||||
distances[i] = gp2y0e_dist16_mm(I2C_PORT) * 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t air_raw(uint8_t index)
|
||||
{
|
||||
if (index >= sizeof(TOF_LIST)) {
|
||||
return 0;
|
||||
}
|
||||
return distances[index];
|
||||
}
|
||||
/*
|
||||
* Chu Pico Air Sensor
|
||||
* WHowe <github.com/whowechina>
|
||||
*
|
||||
* Use ToF (Sharp GP2Y0E03) to detect air keys
|
||||
*/
|
||||
|
||||
#include "air.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "hardware/gpio.h"
|
||||
|
||||
#include "board_defs.h"
|
||||
#include "config.h"
|
||||
|
||||
#include "gp2y0e.h"
|
||||
#include "vl53l0x.h"
|
||||
#include "i2c_hub.h"
|
||||
|
||||
static const uint8_t TOF_LIST[] = TOF_MUX_LIST;
|
||||
static uint8_t tof_model[sizeof(TOF_LIST)];
|
||||
static uint16_t distances[sizeof(TOF_LIST)];
|
||||
|
||||
void air_init()
|
||||
{
|
||||
i2c_init(I2C_PORT, I2C_FREQ);
|
||||
gpio_set_function(I2C_SDA, GPIO_FUNC_I2C);
|
||||
gpio_set_function(I2C_SCL, GPIO_FUNC_I2C);
|
||||
gpio_pull_up(I2C_SDA);
|
||||
gpio_pull_up(I2C_SCL);
|
||||
|
||||
i2c_hub_init();
|
||||
vl53l0x_init(I2C_PORT, 0);
|
||||
|
||||
for (int i = 0; i < sizeof(TOF_LIST); i++) {
|
||||
i2c_select(I2C_PORT, 1 << TOF_LIST[i]);
|
||||
if (vl53l0x_is_present()) {
|
||||
tof_model[i] = 1;
|
||||
} else if (gp2y0e_is_present(I2C_PORT)) {
|
||||
tof_model[i] = 2;
|
||||
} else {
|
||||
tof_model[i] = 0;
|
||||
}
|
||||
if (tof_model[i] == 1) {
|
||||
vl53l0x_init_tof(i);
|
||||
vl53l0x_start_continuous(i);
|
||||
} else if (tof_model[i] == 2) {
|
||||
gp2y03_init(I2C_PORT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t air_num()
|
||||
{
|
||||
return sizeof(TOF_LIST);
|
||||
}
|
||||
|
||||
static inline uint8_t air_bits(int dist, int offset)
|
||||
{
|
||||
if ((dist < offset) || (dist == 4095)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pitch = chu_cfg->tof.pitch * 10;
|
||||
int index = (dist - offset) / pitch;
|
||||
if (index >= 6) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1 << index;
|
||||
}
|
||||
|
||||
uint8_t air_bitmap()
|
||||
{
|
||||
int offset = chu_cfg->tof.offset * 10;
|
||||
int pitch = chu_cfg->tof.pitch * 10;
|
||||
uint8_t bitmap = 0;
|
||||
for (int i = 0; i < sizeof(TOF_LIST); i++) {
|
||||
bitmap |= air_bits(distances[i], offset) |
|
||||
air_bits(distances[i], offset + pitch);
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
unsigned air_value(uint8_t index)
|
||||
{
|
||||
if (index >= sizeof(TOF_LIST)) {
|
||||
return 0;
|
||||
}
|
||||
int offset = chu_cfg->tof.offset * 10;
|
||||
int pitch = chu_cfg->tof.pitch * 10;
|
||||
uint8_t bitmap = air_bits(distances[index], offset) |
|
||||
air_bits(distances[index], offset + pitch);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (bitmap & (1 << i)) {
|
||||
return i + 1; // lowest detected position
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void air_update()
|
||||
{
|
||||
for (int i = 0; i < sizeof(TOF_LIST); i++) {
|
||||
i2c_select(I2C_PORT, 1 << TOF_LIST[i]);
|
||||
if (tof_model[i] == 1) {
|
||||
distances[i] = readRangeContinuousMillimeters(i) * 10;
|
||||
} else if (tof_model[i] == 2) {
|
||||
distances[i] = gp2y0e_dist16_mm(I2C_PORT) * 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t air_raw(uint8_t index)
|
||||
{
|
||||
if (index >= sizeof(TOF_LIST)) {
|
||||
return 0;
|
||||
}
|
||||
return distances[index];
|
||||
}
|
||||
|
||||
+177
-178
@@ -1,178 +1,177 @@
|
||||
/*
|
||||
* RGB LED (WS2812) Strip control
|
||||
* WHowe <github.com/whowechina>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "rgb.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "bsp/board.h"
|
||||
#include "hardware/pio.h"
|
||||
#include "hardware/timer.h"
|
||||
|
||||
#include "ws2812.pio.h"
|
||||
|
||||
#include "board_defs.h"
|
||||
#include "config.h"
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
static uint32_t rgb_buf[47]; // 16(Keys) + 15(Gaps) + 16(maximum ToF indicators)
|
||||
|
||||
#define _MAP_LED(x) _MAKE_MAPPER(x)
|
||||
#define _MAKE_MAPPER(x) MAP_LED_##x
|
||||
#define MAP_LED_RGB { c1 = r; c2 = g; c3 = b; }
|
||||
#define MAP_LED_GRB { c1 = g; c2 = r; c3 = b; }
|
||||
|
||||
#define REMAP_BUTTON_RGB _MAP_LED(BUTTON_RGB_ORDER)
|
||||
#define REMAP_TT_RGB _MAP_LED(TT_RGB_ORDER)
|
||||
|
||||
static inline uint32_t _rgb32(uint32_t c1, uint32_t c2, uint32_t c3, bool gamma_fix)
|
||||
{
|
||||
if (gamma_fix) {
|
||||
c1 = ((c1 + 1) * (c1 + 1) - 1) >> 8;
|
||||
c2 = ((c2 + 1) * (c2 + 1) - 1) >> 8;
|
||||
c3 = ((c3 + 1) * (c3 + 1) - 1) >> 8;
|
||||
}
|
||||
|
||||
return (c1 << 16) | (c2 << 8) | (c3 << 0);
|
||||
}
|
||||
|
||||
uint32_t rgb32(uint32_t r, uint32_t g, uint32_t b, bool gamma_fix)
|
||||
{
|
||||
#if BUTTON_RGB_ORDER == GRB
|
||||
return _rgb32(g, r, b, gamma_fix);
|
||||
#else
|
||||
return _rgb32(r, g, b, 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;
|
||||
uint64_t now = time_us_64();
|
||||
if (now - last < 4000) { // no faster than 250Hz
|
||||
return;
|
||||
}
|
||||
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++) {
|
||||
pio_sm_put_blocking(pio0, 0, rgb_buf[i] << 8u);
|
||||
}
|
||||
}
|
||||
|
||||
void rgb_set_colors(const uint32_t *colors, unsigned index, size_t num)
|
||||
{
|
||||
if (index >= ARRAY_SIZE(rgb_buf)) {
|
||||
return;
|
||||
}
|
||||
if (index + num > ARRAY_SIZE(rgb_buf)) {
|
||||
num = ARRAY_SIZE(rgb_buf) - index;
|
||||
}
|
||||
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 * chu_cfg->style.level / 255;
|
||||
g = g * chu_cfg->style.level / 255;
|
||||
b = b * chu_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] = apply_level(color);
|
||||
}
|
||||
|
||||
void rgb_key_color(unsigned index, uint32_t color)
|
||||
{
|
||||
if (index > 16) {
|
||||
return;
|
||||
}
|
||||
rgb_buf[index * 2] = apply_level(color);
|
||||
}
|
||||
|
||||
void rgb_gap_color(unsigned index, uint32_t color)
|
||||
{
|
||||
if (index > 15) {
|
||||
return;
|
||||
}
|
||||
rgb_buf[index * 2 + 1] = apply_level(color);
|
||||
}
|
||||
|
||||
void rgb_set_brg(unsigned index, const uint8_t *brg_array, size_t num)
|
||||
{
|
||||
if (index >= ARRAY_SIZE(rgb_buf)) {
|
||||
return;
|
||||
}
|
||||
if (index + num > ARRAY_SIZE(rgb_buf)) {
|
||||
num = ARRAY_SIZE(rgb_buf) - index;
|
||||
}
|
||||
for (int i = 0; i < num; i++) {
|
||||
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] = apply_level(rgb32(r, g, b, false));
|
||||
}
|
||||
}
|
||||
|
||||
void rgb_init()
|
||||
{
|
||||
uint pio0_offset = pio_add_program(pio0, &ws2812_program);
|
||||
|
||||
gpio_set_drive_strength(RGB_PIN, GPIO_DRIVE_STRENGTH_2MA);
|
||||
ws2812_program_init(pio0, 0, pio0_offset, RGB_PIN, 800000, false);
|
||||
}
|
||||
|
||||
void rgb_update()
|
||||
{
|
||||
drive_led();
|
||||
}
|
||||
/*
|
||||
* RGB LED (WS2812) Strip control
|
||||
* WHowe <github.com/whowechina>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "rgb.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "hardware/pio.h"
|
||||
#include "hardware/timer.h"
|
||||
|
||||
#include "ws2812.pio.h"
|
||||
|
||||
#include "board_defs.h"
|
||||
#include "config.h"
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
static uint32_t rgb_buf[47]; // 16(Keys) + 15(Gaps) + 16(maximum ToF indicators)
|
||||
|
||||
#define _MAP_LED(x) _MAKE_MAPPER(x)
|
||||
#define _MAKE_MAPPER(x) MAP_LED_##x
|
||||
#define MAP_LED_RGB { c1 = r; c2 = g; c3 = b; }
|
||||
#define MAP_LED_GRB { c1 = g; c2 = r; c3 = b; }
|
||||
|
||||
#define REMAP_BUTTON_RGB _MAP_LED(BUTTON_RGB_ORDER)
|
||||
#define REMAP_TT_RGB _MAP_LED(TT_RGB_ORDER)
|
||||
|
||||
static inline uint32_t _rgb32(uint32_t c1, uint32_t c2, uint32_t c3, bool gamma_fix)
|
||||
{
|
||||
if (gamma_fix) {
|
||||
c1 = ((c1 + 1) * (c1 + 1) - 1) >> 8;
|
||||
c2 = ((c2 + 1) * (c2 + 1) - 1) >> 8;
|
||||
c3 = ((c3 + 1) * (c3 + 1) - 1) >> 8;
|
||||
}
|
||||
|
||||
return (c1 << 16) | (c2 << 8) | (c3 << 0);
|
||||
}
|
||||
|
||||
uint32_t rgb32(uint32_t r, uint32_t g, uint32_t b, bool gamma_fix)
|
||||
{
|
||||
#if BUTTON_RGB_ORDER == GRB
|
||||
return _rgb32(g, r, b, gamma_fix);
|
||||
#else
|
||||
return _rgb32(r, g, b, 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;
|
||||
uint64_t now = time_us_64();
|
||||
if (now - last < 4000) { // no faster than 250Hz
|
||||
return;
|
||||
}
|
||||
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++) {
|
||||
pio_sm_put_blocking(pio0, 0, rgb_buf[i] << 8u);
|
||||
}
|
||||
}
|
||||
|
||||
void rgb_set_colors(const uint32_t *colors, unsigned index, size_t num)
|
||||
{
|
||||
if (index >= ARRAY_SIZE(rgb_buf)) {
|
||||
return;
|
||||
}
|
||||
if (index + num > ARRAY_SIZE(rgb_buf)) {
|
||||
num = ARRAY_SIZE(rgb_buf) - index;
|
||||
}
|
||||
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 * chu_cfg->style.level / 255;
|
||||
g = g * chu_cfg->style.level / 255;
|
||||
b = b * chu_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] = apply_level(color);
|
||||
}
|
||||
|
||||
void rgb_key_color(unsigned index, uint32_t color)
|
||||
{
|
||||
if (index > 16) {
|
||||
return;
|
||||
}
|
||||
rgb_buf[index * 2] = apply_level(color);
|
||||
}
|
||||
|
||||
void rgb_gap_color(unsigned index, uint32_t color)
|
||||
{
|
||||
if (index > 15) {
|
||||
return;
|
||||
}
|
||||
rgb_buf[index * 2 + 1] = apply_level(color);
|
||||
}
|
||||
|
||||
void rgb_set_brg(unsigned index, const uint8_t *brg_array, size_t num)
|
||||
{
|
||||
if (index >= ARRAY_SIZE(rgb_buf)) {
|
||||
return;
|
||||
}
|
||||
if (index + num > ARRAY_SIZE(rgb_buf)) {
|
||||
num = ARRAY_SIZE(rgb_buf) - index;
|
||||
}
|
||||
for (int i = 0; i < num; i++) {
|
||||
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] = apply_level(rgb32(r, g, b, false));
|
||||
}
|
||||
}
|
||||
|
||||
void rgb_init()
|
||||
{
|
||||
uint pio0_offset = pio_add_program(pio0, &ws2812_program);
|
||||
|
||||
gpio_set_drive_strength(RGB_PIN, GPIO_DRIVE_STRENGTH_2MA);
|
||||
ws2812_program_init(pio0, 0, pio0_offset, RGB_PIN, 800000, false);
|
||||
}
|
||||
|
||||
void rgb_update()
|
||||
{
|
||||
drive_led();
|
||||
}
|
||||
|
||||
+177
-178
@@ -1,178 +1,177 @@
|
||||
/*
|
||||
* Controller Config Save and Load
|
||||
* WHowe <github.com/whowechina>
|
||||
*
|
||||
* Config is stored in last sector of flash
|
||||
*/
|
||||
|
||||
#include "save.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <memory.h>
|
||||
|
||||
|
||||
#include "bsp/board.h"
|
||||
#include "pico/bootrom.h"
|
||||
#include "pico/stdio.h"
|
||||
|
||||
#include "hardware/flash.h"
|
||||
#include "pico/multicore.h"
|
||||
#include "pico/unique_id.h"
|
||||
|
||||
static struct {
|
||||
size_t size;
|
||||
size_t offset;
|
||||
void (*after_load)();
|
||||
} modules[8] = {0};
|
||||
static int module_num = 0;
|
||||
|
||||
static uint32_t my_magic = 0xcafecafe;
|
||||
|
||||
#define SAVE_TIMEOUT_US 5000000
|
||||
|
||||
#define SAVE_SECTOR_OFFSET (PICO_FLASH_SIZE_BYTES - FLASH_SECTOR_SIZE)
|
||||
|
||||
typedef struct __attribute ((packed)) {
|
||||
uint32_t magic;
|
||||
uint8_t data[FLASH_PAGE_SIZE - 4];
|
||||
} page_t;
|
||||
|
||||
static page_t old_data = {0};
|
||||
static page_t new_data = {0};
|
||||
static page_t default_data = {0};
|
||||
static int data_page = -1;
|
||||
|
||||
static bool requesting_save = false;
|
||||
static uint64_t requesting_time = 0;
|
||||
|
||||
static mutex_t *io_lock;
|
||||
|
||||
static void save_program()
|
||||
{
|
||||
old_data = new_data;
|
||||
|
||||
data_page = (data_page + 1) % (FLASH_SECTOR_SIZE / FLASH_PAGE_SIZE);
|
||||
printf("\nProgram Flash %d %8lx\n", data_page, old_data.magic);
|
||||
if (mutex_enter_timeout_us(io_lock, 100000)) {
|
||||
sleep_ms(10); /* wait for all io operations to finish */
|
||||
uint32_t ints = save_and_disable_interrupts();
|
||||
if (data_page == 0) {
|
||||
flash_range_erase(SAVE_SECTOR_OFFSET, FLASH_SECTOR_SIZE);
|
||||
}
|
||||
flash_range_program(SAVE_SECTOR_OFFSET + data_page * FLASH_PAGE_SIZE,
|
||||
(uint8_t *)&old_data, FLASH_PAGE_SIZE);
|
||||
restore_interrupts(ints);
|
||||
mutex_exit(io_lock);
|
||||
} else {
|
||||
printf("Program Flash Failed.\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void load_default()
|
||||
{
|
||||
printf("Load Default\n");
|
||||
new_data = default_data;
|
||||
new_data.magic = my_magic;
|
||||
}
|
||||
|
||||
static const page_t *get_page(int id)
|
||||
{
|
||||
int addr = XIP_BASE + SAVE_SECTOR_OFFSET;
|
||||
return (page_t *)(addr + FLASH_PAGE_SIZE * id);
|
||||
}
|
||||
|
||||
static void save_load()
|
||||
{
|
||||
for (int i = 0; i < FLASH_SECTOR_SIZE / FLASH_PAGE_SIZE; i++) {
|
||||
if (get_page(i)->magic != my_magic) {
|
||||
break;
|
||||
}
|
||||
data_page = i;
|
||||
}
|
||||
|
||||
if (data_page < 0) {
|
||||
load_default();
|
||||
save_request(false);
|
||||
return;
|
||||
}
|
||||
|
||||
old_data = *get_page(data_page);
|
||||
new_data = old_data;
|
||||
printf("Page Loaded %d %8lx\n", data_page, new_data.magic);
|
||||
}
|
||||
|
||||
static void save_loaded()
|
||||
{
|
||||
for (int i = 0; i < module_num; i++) {
|
||||
modules[i].after_load();
|
||||
}
|
||||
}
|
||||
|
||||
static union __attribute__((packed)) {
|
||||
pico_unique_board_id_t id;
|
||||
struct {
|
||||
uint32_t id32h;
|
||||
uint32_t id32l;
|
||||
};
|
||||
uint64_t id64;
|
||||
} board_id;
|
||||
|
||||
uint32_t board_id_32()
|
||||
{
|
||||
pico_get_unique_board_id(&board_id.id);
|
||||
return board_id.id32h ^ board_id.id32l;
|
||||
}
|
||||
|
||||
uint64_t board_id_64()
|
||||
{
|
||||
pico_get_unique_board_id(&board_id.id);
|
||||
return board_id.id64;
|
||||
}
|
||||
|
||||
void save_init(uint32_t magic, mutex_t *locker)
|
||||
{
|
||||
my_magic = magic;
|
||||
io_lock = locker;
|
||||
save_load();
|
||||
save_loop();
|
||||
save_loaded();
|
||||
}
|
||||
|
||||
void save_loop()
|
||||
{
|
||||
if (requesting_save && (time_us_64() - requesting_time > SAVE_TIMEOUT_US)) {
|
||||
requesting_save = false;
|
||||
/* only when data is actually changed */
|
||||
if (memcmp(&old_data, &new_data, sizeof(old_data)) == 0) {
|
||||
return;
|
||||
}
|
||||
save_program();
|
||||
}
|
||||
}
|
||||
|
||||
void *save_alloc(size_t size, void *def, void (*after_load)())
|
||||
{
|
||||
modules[module_num].size = size;
|
||||
size_t offset = module_num > 0 ? modules[module_num - 1].offset + size : 0;
|
||||
modules[module_num].offset = offset;
|
||||
modules[module_num].after_load = after_load;
|
||||
module_num++;
|
||||
memcpy(default_data.data + offset, def, size); // backup the default
|
||||
return new_data.data + offset;
|
||||
}
|
||||
|
||||
void save_request(bool immediately)
|
||||
{
|
||||
if (!requesting_save) {
|
||||
printf("Save requested.\n");
|
||||
requesting_save = true;
|
||||
new_data.magic = my_magic;
|
||||
requesting_time = time_us_64();
|
||||
}
|
||||
if (immediately) {
|
||||
requesting_time = 0;
|
||||
save_loop();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Controller Config Save and Load
|
||||
* WHowe <github.com/whowechina>
|
||||
*
|
||||
* Config is stored in last sector of flash
|
||||
*/
|
||||
|
||||
#include "save.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "pico/bootrom.h"
|
||||
#include "pico/stdio.h"
|
||||
|
||||
#include "hardware/flash.h"
|
||||
#include "pico/multicore.h"
|
||||
#include "pico/unique_id.h"
|
||||
|
||||
static struct {
|
||||
size_t size;
|
||||
size_t offset;
|
||||
void (*after_load)();
|
||||
} modules[8] = {0};
|
||||
static int module_num = 0;
|
||||
|
||||
static uint32_t my_magic = 0xcafecafe;
|
||||
|
||||
#define SAVE_TIMEOUT_US 5000000
|
||||
|
||||
#define SAVE_SECTOR_OFFSET (PICO_FLASH_SIZE_BYTES - FLASH_SECTOR_SIZE)
|
||||
|
||||
typedef struct __attribute ((packed)) {
|
||||
uint32_t magic;
|
||||
uint8_t data[FLASH_PAGE_SIZE - 4];
|
||||
} page_t;
|
||||
|
||||
static page_t old_data = {0};
|
||||
static page_t new_data = {0};
|
||||
static page_t default_data = {0};
|
||||
static int data_page = -1;
|
||||
|
||||
static bool requesting_save = false;
|
||||
static uint64_t requesting_time = 0;
|
||||
|
||||
static mutex_t *io_lock;
|
||||
|
||||
static void save_program()
|
||||
{
|
||||
old_data = new_data;
|
||||
|
||||
data_page = (data_page + 1) % (FLASH_SECTOR_SIZE / FLASH_PAGE_SIZE);
|
||||
printf("\nProgram Flash %d %8lx\n", data_page, old_data.magic);
|
||||
if (mutex_enter_timeout_us(io_lock, 100000)) {
|
||||
sleep_ms(10); /* wait for all io operations to finish */
|
||||
uint32_t ints = save_and_disable_interrupts();
|
||||
if (data_page == 0) {
|
||||
flash_range_erase(SAVE_SECTOR_OFFSET, FLASH_SECTOR_SIZE);
|
||||
}
|
||||
flash_range_program(SAVE_SECTOR_OFFSET + data_page * FLASH_PAGE_SIZE,
|
||||
(uint8_t *)&old_data, FLASH_PAGE_SIZE);
|
||||
restore_interrupts(ints);
|
||||
mutex_exit(io_lock);
|
||||
} else {
|
||||
printf("Program Flash Failed.\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void load_default()
|
||||
{
|
||||
printf("Load Default\n");
|
||||
new_data = default_data;
|
||||
new_data.magic = my_magic;
|
||||
}
|
||||
|
||||
static const page_t *get_page(int id)
|
||||
{
|
||||
int addr = XIP_BASE + SAVE_SECTOR_OFFSET;
|
||||
return (page_t *)(addr + FLASH_PAGE_SIZE * id);
|
||||
}
|
||||
|
||||
static void save_load()
|
||||
{
|
||||
for (int i = 0; i < FLASH_SECTOR_SIZE / FLASH_PAGE_SIZE; i++) {
|
||||
if (get_page(i)->magic != my_magic) {
|
||||
break;
|
||||
}
|
||||
data_page = i;
|
||||
}
|
||||
|
||||
if (data_page < 0) {
|
||||
load_default();
|
||||
save_request(false);
|
||||
return;
|
||||
}
|
||||
|
||||
old_data = *get_page(data_page);
|
||||
new_data = old_data;
|
||||
printf("Page Loaded %d %8lx\n", data_page, new_data.magic);
|
||||
}
|
||||
|
||||
static void save_loaded()
|
||||
{
|
||||
for (int i = 0; i < module_num; i++) {
|
||||
modules[i].after_load();
|
||||
}
|
||||
}
|
||||
|
||||
static union __attribute__((packed)) {
|
||||
pico_unique_board_id_t id;
|
||||
struct {
|
||||
uint32_t id32h;
|
||||
uint32_t id32l;
|
||||
};
|
||||
uint64_t id64;
|
||||
} board_id;
|
||||
|
||||
uint32_t board_id_32()
|
||||
{
|
||||
pico_get_unique_board_id(&board_id.id);
|
||||
return board_id.id32h ^ board_id.id32l;
|
||||
}
|
||||
|
||||
uint64_t board_id_64()
|
||||
{
|
||||
pico_get_unique_board_id(&board_id.id);
|
||||
return board_id.id64;
|
||||
}
|
||||
|
||||
void save_init(uint32_t magic, mutex_t *locker)
|
||||
{
|
||||
my_magic = magic;
|
||||
io_lock = locker;
|
||||
save_load();
|
||||
save_loop();
|
||||
save_loaded();
|
||||
}
|
||||
|
||||
void save_loop()
|
||||
{
|
||||
if (requesting_save && (time_us_64() - requesting_time > SAVE_TIMEOUT_US)) {
|
||||
requesting_save = false;
|
||||
/* only when data is actually changed */
|
||||
if (memcmp(&old_data, &new_data, sizeof(old_data)) == 0) {
|
||||
return;
|
||||
}
|
||||
save_program();
|
||||
}
|
||||
}
|
||||
|
||||
void *save_alloc(size_t size, void *def, void (*after_load)())
|
||||
{
|
||||
modules[module_num].size = size;
|
||||
size_t offset = module_num > 0 ? modules[module_num - 1].offset + size : 0;
|
||||
modules[module_num].offset = offset;
|
||||
modules[module_num].after_load = after_load;
|
||||
module_num++;
|
||||
memcpy(default_data.data + offset, def, size); // backup the default
|
||||
return new_data.data + offset;
|
||||
}
|
||||
|
||||
void save_request(bool immediately)
|
||||
{
|
||||
if (!requesting_save) {
|
||||
printf("Save requested.\n");
|
||||
requesting_save = true;
|
||||
new_data.magic = my_magic;
|
||||
requesting_time = time_us_64();
|
||||
}
|
||||
if (immediately) {
|
||||
requesting_time = 0;
|
||||
save_loop();
|
||||
}
|
||||
}
|
||||
|
||||
+102
-103
@@ -1,103 +1,102 @@
|
||||
/*
|
||||
* Chu Pico Silder Keys
|
||||
* WHowe <github.com/whowechina>
|
||||
*
|
||||
* MPR121 CapSense based Keys
|
||||
*/
|
||||
|
||||
#include "slider.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "bsp/board.h"
|
||||
#include "hardware/gpio.h"
|
||||
#include "hardware/i2c.h"
|
||||
|
||||
#include "board_defs.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "mpr121.h"
|
||||
|
||||
#define MPR121_ADDR 0x5A
|
||||
|
||||
static uint16_t readout[36];
|
||||
static uint16_t touch[3];
|
||||
static unsigned touch_count[36];
|
||||
|
||||
void slider_init()
|
||||
{
|
||||
i2c_init(I2C_PORT, I2C_FREQ);
|
||||
gpio_set_function(I2C_SDA, GPIO_FUNC_I2C);
|
||||
gpio_set_function(I2C_SCL, GPIO_FUNC_I2C);
|
||||
gpio_pull_up(I2C_SDA);
|
||||
gpio_pull_up(I2C_SCL);
|
||||
|
||||
for (int m = 0; m < 3; m++) {
|
||||
mpr121_init(MPR121_ADDR + m);
|
||||
}
|
||||
slider_update_config();
|
||||
}
|
||||
|
||||
void slider_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_count[m * 12 + i]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const uint16_t *slider_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 slider_touched(unsigned key)
|
||||
{
|
||||
if (key >= 32) {
|
||||
return 0;
|
||||
}
|
||||
return touch[key / 12] & (1 << (key % 12));
|
||||
}
|
||||
|
||||
unsigned slider_count(unsigned key)
|
||||
{
|
||||
if (key >= 32) {
|
||||
return 0;
|
||||
}
|
||||
return touch_count[key];
|
||||
}
|
||||
|
||||
void slider_reset_stat()
|
||||
{
|
||||
memset(touch_count, 0, sizeof(touch_count));
|
||||
}
|
||||
|
||||
void slider_update_config()
|
||||
{
|
||||
for (int m = 0; m < 3; m++) {
|
||||
mpr121_debounce(MPR121_ADDR + m, chu_cfg->sense.debounce_touch,
|
||||
chu_cfg->sense.debounce_release);
|
||||
mpr121_sense(MPR121_ADDR + m, chu_cfg->sense.global,
|
||||
chu_cfg->sense.keys + m * 12,
|
||||
m != 2 ? 12 : 8);
|
||||
mpr121_filter(MPR121_ADDR + m, chu_cfg->sense.filter >> 6,
|
||||
(chu_cfg->sense.filter >> 4) & 0x03,
|
||||
chu_cfg->sense.filter & 0x07);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Chu Pico Silder Keys
|
||||
* WHowe <github.com/whowechina>
|
||||
*
|
||||
* MPR121 CapSense based Keys
|
||||
*/
|
||||
|
||||
#include "slider.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "hardware/gpio.h"
|
||||
#include "hardware/i2c.h"
|
||||
|
||||
#include "board_defs.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "mpr121.h"
|
||||
|
||||
#define MPR121_ADDR 0x5A
|
||||
|
||||
static uint16_t readout[36];
|
||||
static uint16_t touch[3];
|
||||
static unsigned touch_count[36];
|
||||
|
||||
void slider_init()
|
||||
{
|
||||
i2c_init(I2C_PORT, I2C_FREQ);
|
||||
gpio_set_function(I2C_SDA, GPIO_FUNC_I2C);
|
||||
gpio_set_function(I2C_SCL, GPIO_FUNC_I2C);
|
||||
gpio_pull_up(I2C_SDA);
|
||||
gpio_pull_up(I2C_SCL);
|
||||
|
||||
for (int m = 0; m < 3; m++) {
|
||||
mpr121_init(MPR121_ADDR + m);
|
||||
}
|
||||
slider_update_config();
|
||||
}
|
||||
|
||||
void slider_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_count[m * 12 + i]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const uint16_t *slider_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 slider_touched(unsigned key)
|
||||
{
|
||||
if (key >= 32) {
|
||||
return 0;
|
||||
}
|
||||
return touch[key / 12] & (1 << (key % 12));
|
||||
}
|
||||
|
||||
unsigned slider_count(unsigned key)
|
||||
{
|
||||
if (key >= 32) {
|
||||
return 0;
|
||||
}
|
||||
return touch_count[key];
|
||||
}
|
||||
|
||||
void slider_reset_stat()
|
||||
{
|
||||
memset(touch_count, 0, sizeof(touch_count));
|
||||
}
|
||||
|
||||
void slider_update_config()
|
||||
{
|
||||
for (int m = 0; m < 3; m++) {
|
||||
mpr121_debounce(MPR121_ADDR + m, chu_cfg->sense.debounce_touch,
|
||||
chu_cfg->sense.debounce_release);
|
||||
mpr121_sense(MPR121_ADDR + m, chu_cfg->sense.global,
|
||||
chu_cfg->sense.keys + m * 12,
|
||||
m != 2 ? 12 : 8);
|
||||
mpr121_filter(MPR121_ADDR + m, chu_cfg->sense.filter >> 6,
|
||||
(chu_cfg->sense.filter >> 4) & 0x03,
|
||||
chu_cfg->sense.filter & 0x07);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,11 +105,6 @@ extern "C" {
|
||||
// HID buffer size Should be sufficient to hold ID (if any) + Data
|
||||
#define CFG_TUD_HID_EP_BUFSIZE 64
|
||||
|
||||
#define CFG_TUD_VENDOR 0
|
||||
|
||||
// HID buffer size Should be sufficient to hold ID (if any) + Data
|
||||
#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 : 128)
|
||||
#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 128)
|
||||
|
||||
+139
-141
@@ -1,141 +1,139 @@
|
||||
#ifndef USB_DESCRIPTORS_H_
|
||||
#define USB_DESCRIPTORS_H_
|
||||
|
||||
#include "common/tusb_common.h"
|
||||
#include "device/usbd.h"
|
||||
|
||||
enum {
|
||||
REPORT_ID_JOYSTICK = 1,
|
||||
REPORT_ID_LED_SLIDER_16 = 4,
|
||||
REPORT_ID_LED_SLIDER_15 = 5,
|
||||
REPORT_ID_LED_TOWER_6 = 6,
|
||||
REPORT_ID_LED_COMPRESSED = 11,
|
||||
};
|
||||
|
||||
// because they are missing from tusb_hid.h
|
||||
#define HID_STRING_INDEX(x) HID_REPORT_ITEM(x, 7, RI_TYPE_LOCAL, 1)
|
||||
#define HID_STRING_INDEX_N(x, n) HID_REPORT_ITEM(x, 7, RI_TYPE_LOCAL, n)
|
||||
#define HID_STRING_MINIMUM(x) HID_REPORT_ITEM(x, 8, RI_TYPE_LOCAL, 1)
|
||||
#define HID_STRING_MINIMUM_N(x, n) HID_REPORT_ITEM(x, 8, RI_TYPE_LOCAL, n)
|
||||
#define HID_STRING_MAXIMUM(x) HID_REPORT_ITEM(x, 9, RI_TYPE_LOCAL, 1)
|
||||
#define HID_STRING_MAXIMUM_N(x, n) HID_REPORT_ITEM(x, 9, RI_TYPE_LOCAL, n)
|
||||
|
||||
// Joystick Report Descriptor Template - Based off Drewol/rp2040-gamecon
|
||||
// Button Map | X | Y
|
||||
#define CHUPICO_REPORT_DESC_JOYSTICK \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
|
||||
HID_USAGE(HID_USAGE_DESKTOP_JOYSTICK), \
|
||||
HID_COLLECTION(HID_COLLECTION_APPLICATION), \
|
||||
HID_REPORT_ID(REPORT_ID_JOYSTICK) \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_BUTTON), \
|
||||
HID_USAGE_MIN(1), HID_USAGE_MAX(16), \
|
||||
HID_LOGICAL_MIN(0), HID_LOGICAL_MAX(1), \
|
||||
HID_REPORT_COUNT(16), HID_REPORT_SIZE(1), \
|
||||
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
|
||||
\
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
|
||||
HID_USAGE(HID_USAGE_DESKTOP_HAT_SWITCH), \
|
||||
HID_LOGICAL_MIN(1), HID_LOGICAL_MAX(8), \
|
||||
HID_PHYSICAL_MIN(0), HID_PHYSICAL_MAX_N(315, 2), \
|
||||
HID_REPORT_SIZE(8), HID_REPORT_COUNT(1), \
|
||||
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
|
||||
\
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
|
||||
HID_USAGE(HID_USAGE_DESKTOP_X), HID_USAGE(HID_USAGE_DESKTOP_Y), \
|
||||
HID_USAGE(HID_USAGE_DESKTOP_Z), HID_USAGE(HID_USAGE_DESKTOP_RX), \
|
||||
HID_LOGICAL_MIN(0x00), HID_LOGICAL_MAX(0xff), /* Analog */ \
|
||||
HID_REPORT_SIZE(8), HID_REPORT_COUNT(4), \
|
||||
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
|
||||
\
|
||||
HID_USAGE_PAGE_N(HID_USAGE_PAGE_VENDOR, 2), \
|
||||
HID_USAGE(0), \
|
||||
HID_LOGICAL_MIN(0x00), HID_LOGICAL_MAX(0xff), \
|
||||
HID_REPORT_SIZE(8), HID_REPORT_COUNT(1), \
|
||||
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
|
||||
HID_COLLECTION_END
|
||||
|
||||
#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 CHUPICO_LED_FOOTER \
|
||||
HID_COLLECTION_END
|
||||
|
||||
// Slider First 16 LEDs (48 rgb zones, BRG order)
|
||||
#define CHUPICO_REPORT_DESC_LED_SLIDER_16 \
|
||||
HID_REPORT_ID(REPORT_ID_LED_SLIDER_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), \
|
||||
HID_USAGE_MIN(1), HID_USAGE_MAX(48), \
|
||||
HID_STRING_MINIMUM(8), HID_STRING_MAXIMUM(55), \
|
||||
HID_OUTPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE)
|
||||
|
||||
// Slider Remaining 15 LEDs (45 rgb zones, BRG order)
|
||||
#define CHUPICO_REPORT_DESC_LED_SLIDER_15 \
|
||||
HID_REPORT_ID(REPORT_ID_LED_SLIDER_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), \
|
||||
HID_USAGE_MIN(49), HID_USAGE_MAX(93), \
|
||||
HID_STRING_MINIMUM(8), HID_STRING_MAXIMUM(52), /* Delta to previous */ \
|
||||
HID_OUTPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE)
|
||||
|
||||
// Tower LEDs (18 rgb zones, BRG order)
|
||||
#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), \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_ORDINAL), \
|
||||
HID_USAGE_MIN(94), HID_USAGE_MAX(111), \
|
||||
HID_STRING_MINIMUM(8), HID_STRING_MAXIMUM(25), /* Delta to previous */ \
|
||||
HID_OUTPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE)
|
||||
|
||||
// LEDs Compressed
|
||||
#define CHUPICO_REPORT_DESC_LED_COMPRESSED \
|
||||
HID_REPORT_ID(REPORT_ID_LED_COMPRESSED) \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_ORDINAL), \
|
||||
HID_USAGE(0x00), \
|
||||
HID_LOGICAL_MIN(0x00), HID_LOGICAL_MAX_N(0x00ff, 2), \
|
||||
HID_REPORT_SIZE(8), HID_REPORT_COUNT(63), \
|
||||
HID_FEATURE(HID_DATA | HID_VARIABLE | HID_ABSOLUTE)
|
||||
|
||||
#define CHUPICO_REPORT_DESC_NKRO \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
|
||||
HID_USAGE(HID_USAGE_DESKTOP_KEYBOARD), \
|
||||
HID_COLLECTION(HID_COLLECTION_APPLICATION), \
|
||||
/* Modifier */ \
|
||||
HID_REPORT_SIZE(1), \
|
||||
HID_REPORT_COUNT(8), \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_KEYBOARD), \
|
||||
HID_USAGE_MIN(224), \
|
||||
HID_USAGE_MAX(231), \
|
||||
HID_LOGICAL_MIN(0), \
|
||||
HID_LOGICAL_MAX(1), \
|
||||
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
|
||||
/* LED output that we don't care */ \
|
||||
HID_REPORT_COUNT(5), \
|
||||
HID_REPORT_SIZE(1), \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_LED), \
|
||||
HID_USAGE_MIN(1), \
|
||||
HID_USAGE_MAX(5), \
|
||||
HID_OUTPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
|
||||
HID_REPORT_COUNT(1), \
|
||||
HID_REPORT_SIZE(3), \
|
||||
HID_OUTPUT(HID_CONSTANT), \
|
||||
/* Full Keyboard Bitmap */ \
|
||||
HID_REPORT_SIZE(1), \
|
||||
HID_REPORT_COUNT(120), \
|
||||
HID_LOGICAL_MIN(0), \
|
||||
HID_LOGICAL_MAX(1), \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_KEYBOARD), \
|
||||
HID_USAGE_MIN(0), \
|
||||
HID_USAGE_MAX(119), \
|
||||
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
|
||||
HID_COLLECTION_END
|
||||
|
||||
// HID_REPORT_ID(REPORT_ID_NKRO)
|
||||
|
||||
#endif /* USB_DESCRIPTORS_H_ */
|
||||
#ifndef USB_DESCRIPTORS_H_
|
||||
#define USB_DESCRIPTORS_H_
|
||||
|
||||
#include "common/tusb_common.h"
|
||||
#include "device/usbd.h"
|
||||
|
||||
enum {
|
||||
REPORT_ID_JOYSTICK = 1,
|
||||
REPORT_ID_LED_SLIDER_16 = 4,
|
||||
REPORT_ID_LED_SLIDER_15 = 5,
|
||||
REPORT_ID_LED_TOWER_6 = 6,
|
||||
REPORT_ID_LED_COMPRESSED = 11,
|
||||
};
|
||||
|
||||
// because they are missing from tusb_hid.h
|
||||
#define HID_STRING_INDEX(x) HID_REPORT_ITEM(x, 7, RI_TYPE_LOCAL, 1)
|
||||
#define HID_STRING_INDEX_N(x, n) HID_REPORT_ITEM(x, 7, RI_TYPE_LOCAL, n)
|
||||
#define HID_STRING_MINIMUM(x) HID_REPORT_ITEM(x, 8, RI_TYPE_LOCAL, 1)
|
||||
#define HID_STRING_MINIMUM_N(x, n) HID_REPORT_ITEM(x, 8, RI_TYPE_LOCAL, n)
|
||||
#define HID_STRING_MAXIMUM(x) HID_REPORT_ITEM(x, 9, RI_TYPE_LOCAL, 1)
|
||||
#define HID_STRING_MAXIMUM_N(x, n) HID_REPORT_ITEM(x, 9, RI_TYPE_LOCAL, n)
|
||||
|
||||
// Joystick Report Descriptor Template - Based off Drewol/rp2040-gamecon
|
||||
// Button Map | X | Y
|
||||
#define CHUPICO_REPORT_DESC_JOYSTICK \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
|
||||
HID_USAGE(HID_USAGE_DESKTOP_JOYSTICK), \
|
||||
HID_COLLECTION(HID_COLLECTION_APPLICATION), \
|
||||
HID_REPORT_ID(REPORT_ID_JOYSTICK) \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_BUTTON), \
|
||||
HID_USAGE_MIN(1), HID_USAGE_MAX(16), \
|
||||
HID_LOGICAL_MIN(0), HID_LOGICAL_MAX(1), \
|
||||
HID_REPORT_COUNT(16), HID_REPORT_SIZE(1), \
|
||||
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
|
||||
\
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
|
||||
HID_USAGE(HID_USAGE_DESKTOP_HAT_SWITCH), \
|
||||
HID_LOGICAL_MIN(1), HID_LOGICAL_MAX(8), \
|
||||
HID_PHYSICAL_MIN(0), HID_PHYSICAL_MAX_N(315, 2), \
|
||||
HID_REPORT_SIZE(8), HID_REPORT_COUNT(1), \
|
||||
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
|
||||
\
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
|
||||
HID_USAGE(HID_USAGE_DESKTOP_X), HID_USAGE(HID_USAGE_DESKTOP_Y), \
|
||||
HID_USAGE(HID_USAGE_DESKTOP_Z), HID_USAGE(HID_USAGE_DESKTOP_RX), \
|
||||
HID_LOGICAL_MIN(0x00), HID_LOGICAL_MAX(0xff), /* Analog */ \
|
||||
HID_REPORT_SIZE(8), HID_REPORT_COUNT(4), \
|
||||
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
|
||||
\
|
||||
HID_USAGE_PAGE_N(HID_USAGE_PAGE_VENDOR, 2), \
|
||||
HID_USAGE(0), \
|
||||
HID_LOGICAL_MIN(0x00), HID_LOGICAL_MAX(0xff), \
|
||||
HID_REPORT_SIZE(8), HID_REPORT_COUNT(1), \
|
||||
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
|
||||
HID_COLLECTION_END
|
||||
|
||||
#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 CHUPICO_LED_FOOTER \
|
||||
HID_COLLECTION_END
|
||||
|
||||
// Slider First 16 LEDs (48 rgb zones, BRG order)
|
||||
#define CHUPICO_REPORT_DESC_LED_SLIDER_16 \
|
||||
HID_REPORT_ID(REPORT_ID_LED_SLIDER_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), \
|
||||
HID_USAGE_MIN(1), HID_USAGE_MAX(48), \
|
||||
HID_STRING_MINIMUM(8), HID_STRING_MAXIMUM(55), \
|
||||
HID_OUTPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE)
|
||||
|
||||
// Slider Remaining 15 LEDs (45 rgb zones, BRG order)
|
||||
#define CHUPICO_REPORT_DESC_LED_SLIDER_15 \
|
||||
HID_REPORT_ID(REPORT_ID_LED_SLIDER_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), \
|
||||
HID_USAGE_MIN(49), HID_USAGE_MAX(93), \
|
||||
HID_STRING_MINIMUM(8), HID_STRING_MAXIMUM(52), /* Delta to previous */ \
|
||||
HID_OUTPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE)
|
||||
|
||||
// Tower LEDs (18 rgb zones, BRG order)
|
||||
#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), \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_ORDINAL), \
|
||||
HID_USAGE_MIN(94), HID_USAGE_MAX(111), \
|
||||
HID_STRING_MINIMUM(8), HID_STRING_MAXIMUM(25), /* Delta to previous */ \
|
||||
HID_OUTPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE)
|
||||
|
||||
// LEDs Compressed
|
||||
#define CHUPICO_REPORT_DESC_LED_COMPRESSED \
|
||||
HID_REPORT_ID(REPORT_ID_LED_COMPRESSED) \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_ORDINAL), \
|
||||
HID_USAGE(0x00), \
|
||||
HID_LOGICAL_MIN(0x00), HID_LOGICAL_MAX_N(0x00ff, 2), \
|
||||
HID_REPORT_SIZE(8), HID_REPORT_COUNT(63), \
|
||||
HID_FEATURE(HID_DATA | HID_VARIABLE | HID_ABSOLUTE)
|
||||
|
||||
#define CHUPICO_REPORT_DESC_NKRO \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_DESKTOP), \
|
||||
HID_USAGE(HID_USAGE_DESKTOP_KEYBOARD), \
|
||||
HID_COLLECTION(HID_COLLECTION_APPLICATION), \
|
||||
/* Modifier */ \
|
||||
HID_REPORT_SIZE(1), \
|
||||
HID_REPORT_COUNT(8), \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_KEYBOARD), \
|
||||
HID_USAGE_MIN(224), \
|
||||
HID_USAGE_MAX(231), \
|
||||
HID_LOGICAL_MIN(0), \
|
||||
HID_LOGICAL_MAX(1), \
|
||||
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
|
||||
/* LED output that we don't care */ \
|
||||
HID_REPORT_COUNT(5), \
|
||||
HID_REPORT_SIZE(1), \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_LED), \
|
||||
HID_USAGE_MIN(1), \
|
||||
HID_USAGE_MAX(5), \
|
||||
HID_OUTPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
|
||||
HID_REPORT_COUNT(1), \
|
||||
HID_REPORT_SIZE(3), \
|
||||
HID_OUTPUT(HID_CONSTANT), \
|
||||
/* Full Keyboard Bitmap */ \
|
||||
HID_REPORT_SIZE(1), \
|
||||
HID_REPORT_COUNT(120), \
|
||||
HID_LOGICAL_MIN(0), \
|
||||
HID_LOGICAL_MAX(1), \
|
||||
HID_USAGE_PAGE(HID_USAGE_PAGE_KEYBOARD), \
|
||||
HID_USAGE_MIN(0), \
|
||||
HID_USAGE_MAX(119), \
|
||||
HID_INPUT(HID_DATA | HID_VARIABLE | HID_ABSOLUTE), \
|
||||
HID_COLLECTION_END
|
||||
|
||||
#endif /* USB_DESCRIPTORS_H_ */
|
||||
|
||||
Reference in New Issue
Block a user