diff --git a/Production/Firmware/geki_pico.uf2 b/Production/Firmware/geki_pico.uf2 index 66b8b32..99308a5 100644 Binary files a/Production/Firmware/geki_pico.uf2 and b/Production/Firmware/geki_pico.uf2 differ diff --git a/firmware/src/airkey.c b/firmware/src/airkey.c index e826012..2944f67 100644 --- a/firmware/src/airkey.c +++ b/firmware/src/airkey.c @@ -38,21 +38,8 @@ static struct { #define TOF_NUM (count_of(tofs)) -static struct { - airkey_side_t side; - uint16_t in_low; - uint16_t in_high; - uint16_t out_low; - uint16_t out_high; -} key_defs[] = { - { SIDE_LEFT, 50, 200, 20, 230 }, - { SIDE_RIGHT, 50, 200, 20, 230 }, - { SIDE_LEFT, 300, 400, 280, 430 }, - { SIDE_RIGHT, 300, 400, 280, 430 } -}; - -#define AIRKEY_NUM (count_of(key_defs)) - +#define AIRKEY_NUM 3 +static bool airkeys[AIRKEY_NUM]; static bool sw_val[AIRKEY_NUM]; /* true if triggered */ static uint64_t sw_freeze_time[AIRKEY_NUM]; @@ -100,7 +87,6 @@ void airkey_init() static uint16_t tof_dist[TOF_NUM]; static uint16_t tof_mix[2]; -static bool airkeys[AIRKEY_NUM]; static void tof_read() { @@ -186,15 +172,23 @@ static void calc_mix() } } -#define BETWEEN(x, a, b) (((x) >= (a)) && ((x) <= (b))) +static inline bool in_bound(uint16_t value, uint16_t low, uint16_t high) +{ + return ((value >= low) && (value <= high)); +} + static bool airkey_read(unsigned index) { - airkey_side_t side = key_defs[index].side; - uint16_t dist = tof_mix[side]; + uint16_t dist = (index == 0) ? tof_mix[SIDE_LEFT] : tof_mix[SIDE_RIGHT]; + if (dist == 0) { + return false; + } + + typeof(geki_cfg->tof.trigger[0]) trigger = geki_cfg->tof.trigger[index]; if (airkeys[index]) { // currently triggered - return BETWEEN(dist, key_defs[index].out_low, key_defs[index].out_high); + return in_bound(dist, trigger.out_low, trigger.out_high); } else { - return BETWEEN(dist, key_defs[index].in_low, key_defs[index].in_high); + return in_bound(dist, trigger.in_low, trigger.in_high); } } @@ -235,18 +229,19 @@ void airkey_update() } } -unsigned airkey_num() +bool airkey_get_left() { - return AIRKEY_NUM; + return airkeys[0]; } -bool airkey_get(unsigned id) +bool airkey_get_right() { - if (id >= AIRKEY_NUM) { - return false; - } + return airkeys[1]; +} - return airkeys[id]; +bool airkey_get_shift() +{ + return airkeys[2]; } unsigned airkey_tof_num() diff --git a/firmware/src/airkey.h b/firmware/src/airkey.h index e6069ec..1db6dfc 100644 --- a/firmware/src/airkey.h +++ b/firmware/src/airkey.h @@ -12,8 +12,10 @@ void airkey_init(); void airkey_update(); -unsigned airkey_num(); -bool airkey_get(unsigned id); + +bool airkey_get_left(); +bool airkey_get_right(); +bool airkey_get_shift(); unsigned airkey_tof_num(); const char *airkey_tof_model(); diff --git a/firmware/src/commands.c b/firmware/src/commands.c index 54abe11..9f462f6 100644 --- a/firmware/src/commands.c +++ b/firmware/src/commands.c @@ -51,13 +51,27 @@ static void disp_hid() printf(" IO4: %s.\n", geki_cfg->hid.joy ? "ON" : "OFF"); } -static void disp_tof() +static void disp_tof_status() { - printf("[TOF]\n"); for (int i = 0; i < airkey_tof_num(); i++) { printf(" TOF %d: %s", i, airkey_tof_model(i)); } printf("\n"); +} + +static void disp_tof_trigger() +{ + const char *names[3] = { "WAD Left", "WAD Right", "Shift (Right)" }; + + for (int i = 0; i < 3; i++) { + typeof(geki_cfg->tof.trigger[0]) trigger = geki_cfg->tof.trigger[i]; + printf(" %s: in[%d-%d], out[%d-%d]\n", names[i], + trigger.in_low, trigger.in_high, trigger.out_low, trigger.out_high); + } +} + +static void disp_tof_mix() +{ for (int i = 0; i < 2; i++) { if (geki_cfg->tof.mix[i].algo > 4) { geki_cfg->tof.mix[i].algo = default_cfg.tof.mix[i].algo; @@ -74,9 +88,22 @@ static void disp_tof() } printf("\n"); } +} + +static void disp_tof_roi() +{ printf(" ROI: %d (only for VL53L1X)\n", geki_cfg->tof.roi); } +static void disp_tof() +{ + printf("[TOF]\n"); + disp_tof_status(); + disp_tof_mix(); + disp_tof_trigger(); + disp_tof_roi(); +} + static void disp_aime() { printf("[AIME]\n"); @@ -273,7 +300,7 @@ static bool handle_tof_roi(int argc, char *argv[]) airkey_tof_update_roi(); config_changed(); - disp_tof(); + disp_tof_roi(); return true; } @@ -309,7 +336,55 @@ static bool handle_tof_mix(int side, int argc, char *argv[]) } geki_cfg->tof.mix[side].algo = algo; config_changed(); - disp_tof(); + disp_tof_mix(); + return true; +} + +static inline bool out_of_bound(int value, int low, int high) +{ + return ((value < low) || (value > high)); +} + +static bool handle_tof_trigger(int argc, char *argv[]) +{ + if ((argc < 3) || (argc > 5)) { + return false; + } + + const char *names[] = { "left", "right", "shift" }; + int side = cli_match_prefix(names, 3, argv[0]); + if (side < 0) { + return false; + } + + int in_low = cli_extract_non_neg_int(argv[1], 0); + int in_high = cli_extract_non_neg_int(argv[2], 0); + if ((in_high < in_low) || + out_of_bound(in_low, 1, 999) || out_of_bound(in_high, 1, 999)) { + return false; + } + + int out_low = in_low; + int out_high = in_high; + if (argc >= 4) { + out_low = cli_extract_non_neg_int(argv[3], 0); + if ((out_low > in_low) || out_of_bound(out_low, 1, 999)) { + return false; + } + } + if (argc == 5) { + out_high = cli_extract_non_neg_int(argv[4], 0); + if ((out_high < in_high) || out_of_bound(out_high, 1, 999)) { + return false; + } + } + + geki_cfg->tof.trigger[side].in_low = in_low; + geki_cfg->tof.trigger[side].in_high = in_high; + geki_cfg->tof.trigger[side].out_low = out_low; + geki_cfg->tof.trigger[side].out_high = out_high; + config_changed(); + disp_tof_trigger(); return true; } @@ -338,15 +413,18 @@ static void handle_tof(int argc, char *argv[]) " tof \n" " tof [strict]\n" " tof [window]\n" + " tof trigger [ [out_high]]\n" " tof diagnose [on|off]\n" - " window: 1..7 (5% ~ 35%)\n"; + " window: 1..7 (5% ~ 35%)\n" + " in_low, in_high, out_low, out_high: 1..999\n" + " in_high>=in_low, out_low<=in_low, out_high>=in_high\n"; if (argc < 1) { printf(usage); return; } - const char *commands[] = { "left", "right", "roi", "diagnose" }; + const char *commands[] = { "left", "right", "roi", "trigger", "diagnose" }; int match = cli_match_prefix(commands, count_of(commands), argv[0]); if (match == 2) { @@ -354,6 +432,10 @@ static void handle_tof(int argc, char *argv[]) return; } } else if (match == 3) { + if (handle_tof_trigger(argc - 1, argv + 1)) { + return; + } + } else if (match == 4) { if (handle_tof_diag(argc - 1, argv + 1)) { return; } diff --git a/firmware/src/config.c b/firmware/src/config.c index fc80d4d..cc2e406 100644 --- a/firmware/src/config.c +++ b/firmware/src/config.c @@ -24,10 +24,14 @@ geki_cfg_t default_cfg = { .tof = { .roi = 12, .mix = { - { .strict = 0, .algo = MIX_MAX, .window = 0 }, - { .strict = 0, .algo = MIX_MAX, .window = 0 }, + { .strict = 1, .algo = MIX_MAX, .window = 0 }, + { .strict = 1, .algo = MIX_MAX, .window = 0 }, + }, + .trigger = { + { 100, 260, 60, 300 }, + { 100, 260, 60, 300 }, + { 400, 500, 380, 530 }, }, - .reserved = { 0 }, }, .sound = { .volume = 127, @@ -43,6 +47,21 @@ geki_runtime_t geki_runtime; static void config_loaded() { + for (int i = 0; i < 2; i++) { + if (geki_cfg->tof.mix[i].algo > MIX_AVG) { + geki_cfg->tof.mix[i].algo = default_cfg.tof.mix[i].algo; + config_changed(); + } + } + + for (int i = 0; i < 3; i++) { + typeof(geki_cfg->tof.trigger[0]) trigger = geki_cfg->tof.trigger[i]; + if ((trigger.in_low == 0) || (trigger.in_high == 0) || + (trigger.out_low == 0) || (trigger.out_high == 0)) { + geki_cfg->tof.trigger[i] = default_cfg.tof.trigger[i]; + config_changed(); + } + } } void config_changed() diff --git a/firmware/src/config.h b/firmware/src/config.h index 55cf0ea..6560e22 100644 --- a/firmware/src/config.h +++ b/firmware/src/config.h @@ -37,7 +37,12 @@ typedef struct __attribute__((packed)) { uint8_t algo:4; uint8_t window:3; } mix[2]; - uint8_t reserved[5]; + struct { + uint16_t in_low; + uint16_t in_high; + uint16_t out_low; + uint16_t out_high; + } trigger[3]; } tof; struct { uint8_t joy : 4; diff --git a/firmware/src/hid.c b/firmware/src/hid.c index 3b8af03..2f08b23 100644 --- a/firmware/src/hid.c +++ b/firmware/src/hid.c @@ -52,7 +52,7 @@ static void gen_hid_buttons() hid_joy.buttons[0] = 0; hid_joy.buttons[1] = 0; - if (airkey_get(3)) { + if (airkey_get_shift()) { if (buttons & 0x40) { hid_joy.buttons[key_test.group] |= (1 << key_test.bit); } @@ -70,10 +70,10 @@ static void gen_hid_buttons() } } - if (!airkey_get(0)) { + if (!airkey_get_left()) { hid_joy.buttons[wad_left.group] |= (1 << wad_left.bit); } - if (!airkey_get(1)) { + if (!airkey_get_right()) { hid_joy.buttons[wad_right.group] |= (1 << wad_right.bit); } } @@ -84,7 +84,7 @@ static void gen_hid_coins() uint8_t lever = lever_read(); static int dec_count = 0; - if (airkey_get(3)) { + if (airkey_get_shift()) { if (lever < last_lever) { dec_count++; } else if (lever > last_lever) { diff --git a/firmware/src/main.c b/firmware/src/main.c index 703051d..1071199 100644 --- a/firmware/src/main.c +++ b/firmware/src/main.c @@ -50,16 +50,15 @@ static void run_lights() uint32_t phase = time_us_32() >> 15; - if (airkey_get(3)) { + if (airkey_get_shift()) { uint32_t phase = (time_us_32() >> 15) % 3; for (int i = 0; i < 3; i++) { light_set(1 + i, phase % 3 == i ? 0x808080 : 0); light_set(33 + i, phase % 3 == i ? 0x808080 : 0); } } else { - for (int i = 0; i < 2; i++) { - light_set_wad(i, airkey_get(i) ? rgb32(0x80, 0, 0xff, false) : 0); - } + light_set_wad(0, airkey_get_left() ? rgb32(0x80, 0, 0xff, false) : 0); + light_set_wad(1, airkey_get_right() ? rgb32(0x80, 0, 0xff, false) : 0); } for (int i = 0; i < 6; i++) { @@ -70,14 +69,14 @@ static void run_lights() static void run_sound() { - if (airkey_get(3)) { + if (airkey_get_shift()) { sound_set(0, false); sound_set(1, false); return; } - sound_set(0, airkey_get(0)); - sound_set(1, airkey_get(1)); + sound_set(0, airkey_get_left()); + sound_set(1, airkey_get_right()); } const int aime_intf = 1;