1
0
mirror of https://github.com/whowechina/chu_pico.git synced 2025-01-19 01:34:03 +01:00

More working command lines

This commit is contained in:
whowechina 2023-09-17 14:17:03 +08:00
parent d1107b8e83
commit 44a8a74824
10 changed files with 159 additions and 95 deletions

Binary file not shown.

View File

@ -14,6 +14,7 @@
#include "hardware/gpio.h" #include "hardware/gpio.h"
#include "board_defs.h" #include "board_defs.h"
#include "config.h"
#include "gp2y0e.h" #include "gp2y0e.h"
#include "i2c_hub.h" #include "i2c_hub.h"
@ -21,10 +22,6 @@
static const uint8_t TOF_LIST[] = TOF_MUX_LIST; static const uint8_t TOF_LIST[] = TOF_MUX_LIST;
static uint16_t distances[sizeof(TOF_LIST)]; static uint16_t distances[sizeof(TOF_LIST)];
const int offset_a = 600;
const int offset_b = 800;
const int pitch = 160;
void air_init() void air_init()
{ {
i2c_init(I2C_PORT, I2C_FREQ); i2c_init(I2C_PORT, I2C_FREQ);
@ -50,9 +47,11 @@ size_t air_num()
static inline uint8_t air_bits(int dist, int offset) static inline uint8_t air_bits(int dist, int offset)
{ {
if (dist < offset) { if ((dist < offset) || (dist == 4095)) {
return 0; return 0;
} }
int pitch = chu_cfg->tof.pitch * 10;
int index = (dist - offset) / pitch; int index = (dist - offset) / pitch;
if (index >= 6) { if (index >= 6) {
return 0; return 0;
@ -63,10 +62,12 @@ static inline uint8_t air_bits(int dist, int offset)
uint8_t air_bitmap() uint8_t air_bitmap()
{ {
int offset = chu_cfg->tof.offset * 10;
int pitch = chu_cfg->tof.pitch * 10;
uint8_t bitmap = 0; uint8_t bitmap = 0;
for (int i = 0; i < sizeof(TOF_LIST); i++) { for (int i = 0; i < sizeof(TOF_LIST); i++) {
bitmap |= air_bits(distances[i], offset_a); bitmap |= air_bits(distances[i], offset) |
bitmap |= air_bits(distances[i], offset_b); air_bits(distances[i], offset + pitch);
} }
return bitmap; return bitmap;
} }
@ -76,13 +77,14 @@ unsigned air_value(uint8_t index)
if (index >= sizeof(TOF_LIST)) { if (index >= sizeof(TOF_LIST)) {
return 0; return 0;
} }
int offset = chu_cfg->tof.offset * 10;
uint8_t bitmap = air_bits(distances[index], offset_a) | int pitch = chu_cfg->tof.pitch * 10;
air_bits(distances[index], offset_b); uint8_t bitmap = air_bits(distances[index], offset) |
air_bits(distances[index], offset + pitch);
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
if (bitmap & (1 << i)) { if (bitmap & (1 << i)) {
return i + 1; return i + 1; // lowest detected position
} }
} }

View File

@ -8,6 +8,7 @@
#include "pico/stdlib.h" #include "pico/stdlib.h"
#include "config.h" #include "config.h"
#include "save.h"
#define SENSE_LIMIT_MAX 8 #define SENSE_LIMIT_MAX 8
#define SENSE_LIMIT_MIN -8 #define SENSE_LIMIT_MIN -8
@ -29,7 +30,7 @@ typedef struct {
command_t commands[MAX_COMMANDS]; command_t commands[MAX_COMMANDS];
int num_commands = 0; int num_commands = 0;
void register_command(char *name, cmd_handler_t handler) static void register_command(char *name, cmd_handler_t handler)
{ {
if (num_commands < MAX_COMMANDS) { if (num_commands < MAX_COMMANDS) {
strcpy(commands[num_commands].name, name); strcpy(commands[num_commands].name, name);
@ -38,7 +39,7 @@ void register_command(char *name, cmd_handler_t handler)
} }
} }
void handle_help(int argc, char *argv[]) static void handle_help(int argc, char *argv[])
{ {
printf("Available commands:\n"); printf("Available commands:\n");
for (int i = 0; i < num_commands; i++) { for (int i = 0; i < num_commands; i++) {
@ -72,7 +73,8 @@ static void list_tof()
static void list_sense() static void list_sense()
{ {
printf("[Sense]\n"); printf("[Sense]\n");
printf(" Global: %d, debounce: %d\n", chu_cfg->sense.global, chu_cfg->sense.debounce); printf(" Global: %d, debounce (touch, release): %d, %d\n", chu_cfg->sense.global,
chu_cfg->sense.debounce_touch, chu_cfg->sense.debounce_release);
printf(" | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11| 12| 13| 14| 15|\n"); printf(" | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11| 12| 13| 14| 15|\n");
printf(" -----------------------------------------------------------------\n"); printf(" -----------------------------------------------------------------\n");
printf(" A |"); printf(" A |");
@ -143,12 +145,12 @@ void fps_count(int core)
counter[core] = 0; counter[core] = 0;
} }
void handle_fps(int argc, char *argv[]) static void handle_fps(int argc, char *argv[])
{ {
printf("FPS: core 0: %d, core 1: %d\n", fps[0], fps[1]); printf("FPS: core 0: %d, core 1: %d\n", fps[0], fps[1]);
} }
void handle_hid(int argc, char *argv[]) static void handle_hid(int argc, char *argv[])
{ {
const char *usage = "Usage: hid <joy|nkro>\n"; const char *usage = "Usage: hid <joy|nkro>\n";
if (argc != 1) { if (argc != 1) {
@ -172,6 +174,52 @@ void handle_hid(int argc, char *argv[])
config_changed(); config_changed();
} }
static int 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 void handle_tof(int argc, char *argv[])
{
const char *usage = "Usage: tof <offset> [pitch]\n"
" offset: 40-255\n"
" pitch: 4-50\n";
if ((argc < 1) || (argc > 2)) {
printf(usage);
return;
}
int offset = chu_cfg->tof.offset;
int pitch = chu_cfg->tof.pitch;
if (argc >= 1) {
offset = extract_non_neg_int(argv[0], 0);
}
if (argc == 2) {
pitch = extract_non_neg_int(argv[1], 0);
}
if ((offset < 40) || (offset > 255) || (pitch < 4) || (pitch > 50)) {
printf(usage);
return;
}
chu_cfg->tof.offset = offset;
chu_cfg->tof.pitch = pitch;
config_changed();
list_tof();
}
static uint8_t *extract_key(const char *param) static uint8_t *extract_key(const char *param)
{ {
int len = strlen(param); int len = strlen(param);
@ -185,22 +233,15 @@ static uint8_t *extract_key(const char *param)
return NULL; return NULL;
} }
int id = 0; int id = extract_non_neg_int(param, len - 1);
for (int i = 0; i < len - 1; i++) { if ((id < 0) || (id > 15)) {
if (!isdigit(param[i])) {
return NULL;
}
id = id * 10 + param[i] - '0';
}
if (id > 15) {
return NULL; return NULL;
} }
return &chu_cfg->sense.keys[id * 2 + offset]; return &chu_cfg->sense.keys[id * 2 + offset];
} }
void handle_sense(int argc, char *argv[]) static void handle_sense(int argc, char *argv[])
{ {
const char *usage = "Usage: sense [key] <+|->\n" const char *usage = "Usage: sense [key] <+|->\n"
"Example:\n" "Example:\n"
@ -214,7 +255,7 @@ void handle_sense(int argc, char *argv[])
} }
int8_t *target = &chu_cfg->sense.global; int8_t *target = &chu_cfg->sense.global;
const char *op = argv[1]; const char *op = argv[argc - 1];
if (argc == 2) { if (argc == 2) {
target = extract_key(argv[0]); target = extract_key(argv[0]);
if (!target) { if (!target) {
@ -240,41 +281,58 @@ void handle_sense(int argc, char *argv[])
list_sense(); list_sense();
} }
void handle_debounce(int argc, char *argv[]) static void handle_debounce(int argc, char *argv[])
{ {
const char *usage = "Usage: debounce <0..32>\n"; const char *usage = "Usage: debounce <touch> [release]\n"
if (argc != 1) { " touch, release: 0-255\n";
if ((argc < 1) || (argc > 2)) {
printf(usage); printf(usage);
return; return;
} }
int num = 0; int touch = chu_cfg->sense.debounce_touch;
for (int i = 0; i < strlen(argv[0]); i++) { int release = chu_cfg->sense.debounce_release;
if (!isdigit(argv[0][i])) { if (argc >= 1) {
printf(usage); touch = extract_non_neg_int(argv[0], 0);
return; }
} if (argc == 2) {
num = num * 10 + argv[0][i] - '0'; release = extract_non_neg_int(argv[1], 0);
} }
if (num > 32) { if ((touch < 0) || (release < 0)) {
printf(usage); printf(usage);
return; return;
} }
chu_cfg->sense.debounce = num; chu_cfg->sense.debounce_touch = touch;
chu_cfg->sense.debounce_release = release;
config_changed(); config_changed();
list_sense();
}
static void handle_save()
{
save_request(true);
}
static void handle_factory_reset()
{
config_factory_reset();
printf("Factory reset done.\n");
} }
void cmd_init() void cmd_init()
{ {
fcntl(0, F_SETFL, O_NONBLOCK);
register_command("?", handle_help); register_command("?", handle_help);
register_command("list", handle_list); register_command("list", handle_list);
register_command("fps", handle_fps); register_command("fps", handle_fps);
register_command("hid", handle_hid); register_command("hid", handle_hid);
register_command("tof", handle_tof);
register_command("sense", handle_sense); register_command("sense", handle_sense);
register_command("debounce", handle_debounce); register_command("debounce", handle_debounce);
register_command("save", handle_save);
register_command("factory", config_factory_reset);
} }
static char cmd_buf[256]; static char cmd_buf[256];

View File

@ -27,10 +27,11 @@ static chu_cfg_t default_cfg = {
}, },
.tof = { .tof = {
.offset = 64, .offset = 64,
.pitch = 16, .pitch = 18,
}, },
.sense = { .sense = {
.debounce = 4, .debounce_touch = 1,
.debounce_release = 8,
}, },
.hid = { .hid = {
.joy = 0x0f, .joy = 0x0f,
@ -46,15 +47,11 @@ static void config_loaded()
chu_cfg->style.level = default_cfg.style.level; chu_cfg->style.level = default_cfg.style.level;
config_changed(); config_changed();
} }
if ((chu_cfg->tof.offset < 400) || (chu_cfg->tof.offset > 2000) || if ((chu_cfg->tof.offset < 40) ||
(chu_cfg->tof.pitch < 50) || (chu_cfg->tof.pitch > 500)) { (chu_cfg->tof.pitch < 4) || (chu_cfg->tof.pitch > 50)) {
chu_cfg->tof = default_cfg.tof; chu_cfg->tof = default_cfg.tof;
config_changed(); config_changed();
} }
if (chu_cfg->sense.debounce > 32) {
chu_cfg->sense.debounce = default_cfg.sense.debounce;
}
} }
void config_changed() void config_changed()

View File

@ -29,7 +29,8 @@ typedef struct __attribute__((packed)) {
} tof; } tof;
struct { struct {
int8_t global; int8_t global;
uint8_t debounce; uint8_t debounce_touch;
uint8_t debounce_release;
int8_t keys[32]; int8_t keys[32];
} sense; } sense;
struct { struct {

View File

@ -60,15 +60,6 @@ void report_usb_hid()
} }
} }
static bool request_core1_pause = false;
static void pause_core1(bool pause)
{
request_core1_pause = pause;
if (pause) {
sleep_ms(5); /* wait for any IO ops to finish */
}
}
static void gen_joy_report() static void gen_joy_report()
{ {
hid_joy.axis = 0; hid_joy.axis = 0;
@ -142,12 +133,15 @@ static void run_lights()
} }
} }
static mutex_t core1_io_lock;
static void core1_loop() static void core1_loop()
{ {
while (1) { while (1) {
run_lights(); if (mutex_try_enter(&core1_io_lock, NULL)) {
rgb_update(); run_lights();
rgb_update();
mutex_exit(&core1_io_lock);
}
slider_update_baseline(); slider_update_baseline();
fps_count(1); fps_count(1);
sleep_ms(1); sleep_ms(1);
@ -180,7 +174,8 @@ void init()
stdio_init_all(); stdio_init_all();
config_init(); config_init();
save_init(0xca34cafe, pause_core1); mutex_init(&core1_io_lock);
save_init(0xca34cafe, &core1_io_lock);
slider_init(); slider_init();
air_init(); air_init();

View File

@ -56,7 +56,7 @@ static void drive_led()
{ {
static uint64_t last = 0; static uint64_t last = 0;
uint64_t now = time_us_64(); uint64_t now = time_us_64();
if (now - last < 5000) { // no faster than 200Hz if (now - last < 4000) { // no faster than 250Hz
return; return;
} }
last = now; last = now;

View File

@ -18,7 +18,7 @@
#include "pico/stdio.h" #include "pico/stdio.h"
#include "hardware/flash.h" #include "hardware/flash.h"
#include "hardware/sync.h" #include "pico/multicore.h"
static struct { static struct {
size_t size; size_t size;
@ -29,6 +29,8 @@ static int module_num = 0;
static uint32_t my_magic = 0xcafecafe; static uint32_t my_magic = 0xcafecafe;
#define SAVE_TIMEOUT_US 30000000
#define SAVE_SECTOR_OFFSET (PICO_FLASH_SIZE_BYTES - FLASH_SECTOR_SIZE) #define SAVE_SECTOR_OFFSET (PICO_FLASH_SIZE_BYTES - FLASH_SECTOR_SIZE)
typedef struct __attribute ((packed)) { typedef struct __attribute ((packed)) {
@ -44,23 +46,27 @@ static int data_page = -1;
static bool requesting_save = false; static bool requesting_save = false;
static uint64_t requesting_time = 0; static uint64_t requesting_time = 0;
static io_locker_func io_lock; static mutex_t *io_lock;
static void save_program() static void save_program()
{ {
old_data = new_data; old_data = new_data;
data_page = (data_page + 1) % (FLASH_SECTOR_SIZE / FLASH_PAGE_SIZE); data_page = (data_page + 1) % (FLASH_SECTOR_SIZE / FLASH_PAGE_SIZE);
printf("Program Flash %d %8lx\n", data_page, old_data.magic); printf("\nProgram Flash %d %8lx\n", data_page, old_data.magic);
io_lock(true); if (mutex_enter_timeout_us(io_lock, 100000)) {
uint32_t ints = save_and_disable_interrupts(); sleep_ms(5); /* wait for all io operations to finish */
if (data_page == 0) { uint32_t ints = save_and_disable_interrupts();
flash_range_erase(SAVE_SECTOR_OFFSET, FLASH_SECTOR_SIZE); 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");
} }
flash_range_program(SAVE_SECTOR_OFFSET + data_page * FLASH_PAGE_SIZE,
(uint8_t *)&old_data, FLASH_PAGE_SIZE);
restore_interrupts(ints);
io_lock(false);
} }
static void load_default() static void load_default()
@ -103,7 +109,7 @@ static void save_loaded()
} }
} }
void save_init(uint32_t magic, io_locker_func locker) void save_init(uint32_t magic, mutex_t *locker)
{ {
my_magic = magic; my_magic = magic;
io_lock = locker; io_lock = locker;
@ -114,17 +120,13 @@ void save_init(uint32_t magic, io_locker_func locker)
void save_loop() void save_loop()
{ {
if (requesting_save && (time_us_64() - requesting_time > 1000000)) { if (requesting_save && (time_us_64() - requesting_time > SAVE_TIMEOUT_US)) {
requesting_save = false; requesting_save = false;
printf("Time to save.\n");
/* only when data is actually changed */ /* only when data is actually changed */
for (int i = 0; i < sizeof(old_data); i++) { if (memcmp(&old_data, &new_data, sizeof(old_data)) == 0) {
if (((uint8_t *)&old_data)[i] != ((uint8_t *)&new_data)[i]) { return;
save_program();
return;
}
} }
printf("No change.\n"); save_program();
} }
} }
@ -142,7 +144,7 @@ void *save_alloc(size_t size, void *def, void (*after_load)())
void save_request(bool immediately) void save_request(bool immediately)
{ {
if (!requesting_save) { if (!requesting_save) {
printf("Save marked.\n"); printf("Save requested.\n");
requesting_save = true; requesting_save = true;
new_data.magic = my_magic; new_data.magic = my_magic;
requesting_time = time_us_64(); requesting_time = time_us_64();

View File

@ -10,9 +10,11 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "pico/multicore.h"
/* It's safer to lock other I/O ops during saving, so we need a locker */ /* It's safer to lock other I/O ops during saving, so we need a locker */
typedef void (*io_locker_func)(bool pause); typedef void (*io_locker_func)(bool pause);
void save_init(uint32_t magic, io_locker_func locker); void save_init(uint32_t magic, mutex_t *lock);
void save_loop(); void save_loop();

View File

@ -28,7 +28,6 @@ static uint16_t baseline[36];
static int16_t error[36]; static int16_t error[36];
static uint16_t readout[36]; static uint16_t readout[36];
static bool touched[36]; static bool touched[36];
static uint16_t debounce[36];
static uint16_t touch[3]; static uint16_t touch[3];
static struct mpr121_sensor mpr121[3]; static struct mpr121_sensor mpr121[3];
@ -139,6 +138,9 @@ int slider_delta(unsigned key)
return readout[key] - baseline[key]; return readout[key] - baseline[key];
} }
static uint16_t touch_count[36];
static uint16_t release_count[36];
bool slider_touched(unsigned key) bool slider_touched(unsigned key)
{ {
if (key >= 32) { if (key >= 32) {
@ -151,18 +153,23 @@ bool slider_touched(unsigned key)
int release_thre = RELEASE_THRESHOLD - bias / 2; int release_thre = RELEASE_THRESHOLD - bias / 2;
if (touched[key]) { if (touched[key]) {
if (delta > touch_thre) { if (delta > release_thre) {
debounce[key] = 0; release_count[key] = 0;
}
if (debounce[key] > chu_cfg->sense.debounce) {
if (delta < release_thre) {
touched[key] = false;
}
} else { } else {
debounce[key]++; release_count[key]++;
}
if (release_count[key] > chu_cfg->sense.debounce_release) {
touch_count[key] = 0;
touched[key] = false;
} }
} else if (!touched[key]) { } else if (!touched[key]) {
if (delta > touch_thre) { if (delta < touch_thre) {
touch_count[key] = 0;
} else {
touch_count[key]++;
}
if (touch_count[key] > chu_cfg->sense.debounce_touch) {
release_count[key] = 0;
touched[key] = true; touched[key] = true;
} }
} }