diff --git a/Production/Firmware/iidx_pico.uf2 b/Production/Firmware/iidx_pico.uf2 index ced4f0f..1464c02 100644 Binary files a/Production/Firmware/iidx_pico.uf2 and b/Production/Firmware/iidx_pico.uf2 differ diff --git a/doc/Firmware_manual.pptx b/doc/Firmware_manual.pptx index 4ec7681..ab156d9 100644 Binary files a/doc/Firmware_manual.pptx and b/doc/Firmware_manual.pptx differ diff --git a/firmware/src/config.c b/firmware/src/config.c index 613109d..e3f66de 100644 --- a/firmware/src/config.c +++ b/firmware/src/config.c @@ -28,10 +28,10 @@ static iidx_cfg_t default_cfg = { .deadzone = 0, }, .effects = { - .play_vol = 255, - .filter = 128, - .eq_low = 128, - .eq_hi = 128, + .e1 = 255, + .e2 = 128, + .e3 = 128, + .e4 = 128, } }; diff --git a/firmware/src/config.h b/firmware/src/config.h index adcfce8..f23336e 100644 --- a/firmware/src/config.h +++ b/firmware/src/config.h @@ -31,10 +31,10 @@ typedef struct __attribute ((packed)) { uint8_t deadzone; /* only for analog */ } tt_sensor; struct { - uint8_t play_vol; - uint8_t filter; - uint8_t eq_low; - uint8_t eq_hi; + uint8_t e1; + uint8_t e2; + uint8_t e3; + uint8_t e4; } effects; } iidx_cfg_t; diff --git a/firmware/src/main.c b/firmware/src/main.c index 46a1edc..7be6584 100644 --- a/firmware/src/main.c +++ b/firmware/src/main.c @@ -39,10 +39,10 @@ struct { void report_usb_hid() { if (tud_hid_ready()) { - hid_report.joy[2] = iidx_cfg->effects.play_vol; - hid_report.joy[3] = iidx_cfg->effects.filter; - hid_report.joy[4] = iidx_cfg->effects.eq_low; - hid_report.joy[5] = iidx_cfg->effects.eq_hi; + hid_report.joy[2] = iidx_cfg->effects.e1; + hid_report.joy[3] = iidx_cfg->effects.e2; + hid_report.joy[4] = iidx_cfg->effects.e3; + hid_report.joy[5] = iidx_cfg->effects.e4; tud_hid_n_report(0x00, REPORT_ID_JOYSTICK, &hid_report, sizeof(hid_report)); } } diff --git a/firmware/src/setup.c b/firmware/src/setup.c index 69b1676..c3c2626 100644 --- a/firmware/src/setup.c +++ b/firmware/src/setup.c @@ -55,10 +55,10 @@ static struct { #define KEY_5 0x0010 #define KEY_6 0x0020 #define KEY_7 0x0040 -#define E_START 0x0080 -#define E_EFFECT 0x0100 -#define E_VEFX 0x0200 -#define E_4 0x0400 +#define E1 0x0080 +#define E2 0x0100 +#define E3 0x0200 +#define E4 0x0400 #define AUX_NO 0x0800 #define AUX_YES 0x1000 @@ -69,16 +69,22 @@ static struct { #define LED_KEY_5 4 #define LED_KEY_6 5 #define LED_KEY_7 6 -#define LED_E_START 7 -#define LED_E_EFFECT 8 -#define LED_E_VEFX 9 -#define LED_E_4 10 +#define LED_E1 7 +#define LED_E2 8 +#define LED_E3 9 +#define LED_E4 10 #define PRESSED_ALL(k) ((input.keys & (k)) == (k)) #define PRESSED_ANY(k) (input.keys & (k)) #define JUST_PRESSED(k) (input.just_pressed & (k)) #define JUST_RELEASED(k) (input.just_released & (k)) +#define RED button_rgb32(99, 0, 0, false) +#define GREEN button_rgb32(0, 99, 0, false) +#define CYAN button_rgb32(0, 40, 99, false) +#define YELLOW button_rgb32(99, 99, 0, false) +#define SILVER button_rgb32(60, 60, 60, false) + typedef void (*mode_func)(); static void join_mode(setup_mode_t new_mode); @@ -97,12 +103,12 @@ static void check_exit() } } -static void mode_none_loop() +static void none_loop() { static bool escaped = false; static uint64_t escape_time = 0; - if (PRESSED_ALL(AUX_NO | AUX_YES | E_START)) { + if (PRESSED_ALL(AUX_NO | AUX_YES | KEY_1 | KEY_3 | KEY_5 | KEY_7)) { reset_usb_boot(0, 2); // usb boot to flash } @@ -119,8 +125,7 @@ static void mode_none_loop() return; } - uint16_t pressed = PRESSED_ANY(E_START | E_EFFECT | E_VEFX | E_4); - if (pressed) { + if (PRESSED_ANY(E1 | E2 | E3 | E4)) { escaped = false; join_mode(MODE_ANALOG); return; @@ -137,22 +142,22 @@ static struct { int16_t start_angle; } tt_ctx; -void mode_tt_enter() +static void tt_enter() { tt_ctx.start_angle = input.angle; } -static void mode_tt_key_change() +static void tt_key_change() { - if (JUST_PRESSED(E_START)) { + if (JUST_PRESSED(E1)) { tt_ctx.adjust_led = (tt_ctx.adjust_led == 1) ? 0 : 1; tt_ctx.start_angle = input.angle; - } else if (JUST_PRESSED(E_EFFECT)) { + } else if (JUST_PRESSED(E2)) { tt_ctx.adjust_led = (tt_ctx.adjust_led == 2) ? 0 : 2; tt_ctx.start_angle = input.angle; - } else if (JUST_PRESSED(E_VEFX)) { + } else if (JUST_PRESSED(E3)) { iidx_cfg->tt_led.mode = (iidx_cfg->tt_led.mode + 1) % 3; - } else if (JUST_PRESSED(E_4)) { + } else if (JUST_PRESSED(E4)) { iidx_cfg->tt_sensor.mode = (iidx_cfg->tt_sensor.mode + 1) % 4; } else if (JUST_PRESSED(KEY_2)) { iidx_cfg->tt_sensor.deadzone = 0; @@ -165,7 +170,7 @@ static void mode_tt_key_change() check_exit(); } -static void mode_tt_rotate() +static void tt_rotate() { int16_t delta = input.angle - tt_ctx.start_angle; if (abs(delta) > 8) { @@ -194,7 +199,7 @@ static void mode_tt_rotate() } } -void mode_tt_loop() +static void tt_loop() { static uint32_t mask = 0xffffff; @@ -210,53 +215,121 @@ void mode_tt_loop() setup_led_tt[head] = tt_rgb32(0xa0, 0, 0, false); setup_led_tt[tail] = tt_rgb32(0, 0xa0, 0, false); - setup_led_button[LED_E_EFFECT] = tt_rgb32(0, 10, 0, false); - setup_led_button[LED_E_START] = tt_rgb32(10, 0, 0, false); + setup_led_button[LED_E2] = tt_rgb32(0, 10, 0, false); + setup_led_button[LED_E1] = tt_rgb32(10, 0, 0, false); if (tt_ctx.adjust_led == 1) { setup_led_tt[head] &= mask; - setup_led_button[LED_E_START] = tt_rgb32(128, 0, 0, false) & mask; + setup_led_button[LED_E1] = tt_rgb32(128, 0, 0, false) & mask; } else if (tt_ctx.adjust_led == 2) { setup_led_tt[tail] &= mask; - setup_led_button[LED_E_EFFECT] = tt_rgb32(0, 128, 0, false) & mask; + setup_led_button[LED_E2] = tt_rgb32(0, 128, 0, false) & mask; } - uint32_t red = button_rgb32(99, 0, 0, false); - uint32_t green = button_rgb32(0, 99, 0, false); - uint32_t cyan = button_rgb32(0, 40, 99, false); - uint32_t yellow = button_rgb32(99, 99, 0, false); - uint32_t silver = button_rgb32(60, 60, 60, false); - switch (iidx_cfg->tt_led.mode) { case 0: - setup_led_button[LED_E_VEFX] = green; + setup_led_button[LED_E3] = GREEN; break; case 1: - setup_led_button[LED_E_VEFX] = red; + setup_led_button[LED_E3] = RED; break; default: - setup_led_button[LED_E_VEFX] = 0; + setup_led_button[LED_E3] = 0; break; } switch (iidx_cfg->tt_sensor.mode) { case 0: - setup_led_button[LED_E_4] = green; + setup_led_button[LED_E4] = GREEN; break; case 1: - setup_led_button[LED_E_4] = red; + setup_led_button[LED_E4] = RED; break; case 2: - setup_led_button[LED_E_4] = cyan; + setup_led_button[LED_E4] = CYAN; break; default: - setup_led_button[LED_E_4] = yellow; + setup_led_button[LED_E4] = YELLOW; break; } - setup_led_button[LED_KEY_2] = iidx_cfg->tt_sensor.deadzone == 0 ? silver : 0; - setup_led_button[LED_KEY_4] = iidx_cfg->tt_sensor.deadzone == 1 ? silver : 0; - setup_led_button[LED_KEY_6] = iidx_cfg->tt_sensor.deadzone == 2 ? silver : 0; + setup_led_button[LED_KEY_2] = iidx_cfg->tt_sensor.deadzone == 0 ? SILVER : 0; + setup_led_button[LED_KEY_4] = iidx_cfg->tt_sensor.deadzone == 1 ? SILVER : 0; + setup_led_button[LED_KEY_6] = iidx_cfg->tt_sensor.deadzone == 2 ? SILVER : 0; +} + +static struct { + uint8_t channel; /* 0:E1(Start), 1:E2(Effect), 2:E3(VEFX), 3:E4 */ + uint8_t *value; + int16_t start_angle; +} analog_ctx; + +static void analog_key_change() +{ + if (JUST_PRESSED(E1)) { + analog_ctx.channel = 0; + analog_ctx.value = &iidx_cfg->effects.e1; + } else if (JUST_PRESSED(E2)) { + analog_ctx.channel = 1; + analog_ctx.value = &iidx_cfg->effects.e2; + } else if (JUST_PRESSED(E3)) { + analog_ctx.channel = 2; + analog_ctx.value = &iidx_cfg->effects.e3; + } else if (JUST_PRESSED(E4)) { + analog_ctx.channel = 3; + analog_ctx.value = &iidx_cfg->effects.e4; + } + check_exit(); +} + +static void analog_enter() +{ + analog_key_change(); +} + +static void analog_rotate() +{ + int16_t new_value = *analog_ctx.value; + new_value += input.rotate; + if (new_value < 0) { + new_value = 0; + } else if (new_value > 255) { + new_value = 255; + } + *analog_ctx.value = new_value; +} + +static void analog_loop() +{ + static uint32_t mask = 0xffffff; + + RUN_EVERY_N_MS(mask = ~mask, 50); + + setup_led_button[LED_E1] = RED; + setup_led_button[LED_E2] = GREEN; + setup_led_button[LED_E3] = CYAN; + setup_led_button[LED_E4] = YELLOW; + + uint32_t color; + if (analog_ctx.channel == 1) { + color = GREEN; + setup_led_button[LED_E2] &= mask; + } else if (analog_ctx.channel == 2) { + color = CYAN; + setup_led_button[LED_E3] &= mask; + } else if (analog_ctx.channel == 3) { + color = YELLOW; + setup_led_button[LED_E4] &= mask; + } else { + color = RED; + setup_led_button[LED_E1] &= mask; + } + + int split = (int)*analog_ctx.value * iidx_cfg->tt_led.num / 255; + + for (int i = 1; i < iidx_cfg->tt_led.num - 1; i++) { + setup_led_tt[i] = i < split ? color : 0; + } } static struct { @@ -265,11 +338,11 @@ static struct { mode_func loop; mode_func enter; } mode_defs[] = { - [MODE_NONE] = { nop, nop, mode_none_loop, nop}, - [MODE_TURNTABLE] = { mode_tt_key_change, mode_tt_rotate, mode_tt_loop, mode_tt_enter}, - [MODE_ANALOG] = { nop, check_exit, nop, nop}, - [MODE_TT_EFFECT] = { nop, check_exit, nop, nop}, - [MODE_KEY_COLOR] = { nop, check_exit, nop, nop}, + [MODE_NONE] = { nop, nop, none_loop, nop}, + [MODE_TURNTABLE] = { tt_key_change, tt_rotate, tt_loop, tt_enter}, + [MODE_ANALOG] = { analog_key_change, analog_rotate, analog_loop, analog_enter}, + [MODE_TT_EFFECT] = { nop, nop, check_exit, nop}, + [MODE_KEY_COLOR] = { nop, nop, check_exit, nop}, }; static void join_mode(setup_mode_t new_mode)