From f2225767a2bb6cc7d643ee7f13aa957542c6471a Mon Sep 17 00:00:00 2001 From: WillyJL Date: Sat, 23 Aug 2025 01:59:31 +0200 Subject: [PATCH 1/5] Give useful names to ledblink*() functions --- firmware/application/src/app_main.c | 32 +++---- firmware/application/src/rfid_main.c | 2 +- firmware/application/src/rgb_marquee.c | 116 ++++++++++++------------- firmware/application/src/rgb_marquee.h | 14 +-- 4 files changed, 82 insertions(+), 82 deletions(-) diff --git a/firmware/application/src/app_main.c b/firmware/application/src/app_main.c index 958638a..8d91bac 100644 --- a/firmware/application/src/app_main.c +++ b/firmware/application/src/app_main.c @@ -314,11 +314,11 @@ static void system_off_enter(void) { color = 2; } } - if (m_system_off_processing) ledblink5(color, slot, dir ? 7 : 0); - if (m_system_off_processing) ledblink4(color, dir, 7, 99, 75); - if (m_system_off_processing) ledblink4(color, !dir, 7, 75, 50); - if (m_system_off_processing) ledblink4(color, dir, 7, 50, 25); - if (m_system_off_processing) ledblink4(color, !dir, 7, 25, 0); + if (m_system_off_processing) rgb_marquee_sweep_from_to(color, slot, dir ? 7 : 0); + if (m_system_off_processing) rgb_marquee_sweep_fade(color, dir, 7, 99, 75); + if (m_system_off_processing) rgb_marquee_sweep_fade(color, !dir, 7, 75, 50); + if (m_system_off_processing) rgb_marquee_sweep_fade(color, dir, 7, 50, 25); + if (m_system_off_processing) rgb_marquee_sweep_fade(color, !dir, 7, 25, 0); } rgb_marquee_stop(); if (!m_system_off_processing) { @@ -460,11 +460,11 @@ static void check_wakeup_src(void) { // Button wake-up boot animation uint8_t animation_config = settings_get_animation_config(); if (animation_config == SettingsAnimationModeFull) { - ledblink2(color, !dir, 11); - ledblink2(color, dir, 11); - ledblink2(color, !dir, dir ? slot : 7 - slot); + rgb_marquee_sweep_to(color, !dir, 11); + rgb_marquee_sweep_to(color, dir, 11); + rgb_marquee_sweep_to(color, !dir, dir ? slot : 7 - slot); } else if (animation_config == SettingsAnimationModeMinimal) { - ledblink2(color, !dir, dir ? slot : 7 - slot); + rgb_marquee_sweep_to(color, !dir, dir ? slot : 7 - slot); } else { set_slot_light_color(color); } @@ -497,7 +497,7 @@ static void check_wakeup_src(void) { uint8_t animation_config = settings_get_animation_config(); if (animation_config == SettingsAnimationModeFull) { // In the case of field wake-up, only one round of RGB is swept as the power-on animation - ledblink2(color, !dir, dir ? slot : 7 - slot); + rgb_marquee_sweep_to(color, !dir, dir ? slot : 7 - slot); } set_slot_light_color(color); light_up_by_slot(); @@ -526,9 +526,9 @@ static void check_wakeup_src(void) { tag_emulation_factory_init(); // RGB - ledblink2(0, !dir, 11); - ledblink2(1, dir, 11); - ledblink2(2, !dir, 11); + rgb_marquee_sweep_to(0, !dir, 11); + rgb_marquee_sweep_to(1, dir, 11); + rgb_marquee_sweep_to(2, !dir, 11); // Show RGB for slot. set_slot_light_color(color); @@ -924,12 +924,12 @@ static void blink_usb_led_status(void) { } } else { // The light effect is enabled and can be displayed - if (is_rgb_marquee_enable()) { + if (rgb_marquee_is_enabled()) { is_working = true; if (g_usb_port_opened) { - ledblink1(color, dir); + rgb_marquee_usb_open_sweep(color, dir); } else { - ledblink6(); + rgb_marquee_usb_idle(); } } else { if (is_working) { diff --git a/firmware/application/src/rfid_main.c b/firmware/application/src/rfid_main.c index f93d448..deb72e7 100644 --- a/firmware/application/src/rfid_main.c +++ b/firmware/application/src/rfid_main.c @@ -94,7 +94,7 @@ void light_up_by_slot(void) { void apply_slot_change(uint8_t slot_now, uint8_t slot_new) { uint8_t color_now = get_color_by_slot(slot_now); uint8_t color_new = get_color_by_slot(slot_new); - ledblink3(slot_now, color_now, slot_new, color_new); + rgb_marquee_slot_switch(slot_now, color_now, slot_new, color_new); } /** diff --git a/firmware/application/src/rgb_marquee.c b/firmware/application/src/rgb_marquee.c index 4241668..341406c 100644 --- a/firmware/application/src/rgb_marquee.c +++ b/firmware/application/src/rgb_marquee.c @@ -32,9 +32,9 @@ nrf_drv_pwm_config_t pwm_config = {//PWM configuration structure .step_mode = NRF_PWM_STEP_AUTO }; static autotimer *timer; -static uint8_t ledblink6_step = 0; -static uint8_t ledblink6_color = RGB_RED; -static uint8_t ledblink1_step = 0; +static uint8_t rgb_marquee_usb_idle_step = 0; +static uint8_t rgb_marquee_usb_idle_color = RGB_RED; +static uint8_t rgb_marquee_usb_open_sweep_step = 0; extern bool g_usb_led_marquee_enable; @@ -45,14 +45,14 @@ void rgb_marquee_init(void) { void rgb_marquee_stop(void) { nrfx_pwm_stop(&pwm0_ins, true); nrfx_pwm_uninit(&pwm0_ins);//turn off pwm output - ledblink6_step = 0; - ledblink1_step = 0; + rgb_marquee_usb_idle_step = 0; + rgb_marquee_usb_open_sweep_step = 0; } // reset RGB state machines to force a refresh of the LED color void rgb_marquee_reset(void) { - ledblink6_step = 0; - ledblink1_step = 0; + rgb_marquee_usb_idle_step = 0; + rgb_marquee_usb_open_sweep_step = 0; } // Brightness to PWM value @@ -62,12 +62,12 @@ uint16_t get_pwmduty(uint8_t light_level) { // 4 Lights and the level of brightness levels (no return) //COLOR 0-R,1-G,2-B -void ledblink1(uint8_t color, uint8_t dir) { +void rgb_marquee_usb_open_sweep(uint8_t color, uint8_t dir) { static uint8_t startled = 0; static uint8_t setled = 0; uint32_t *led_pins_arr; - if (!g_usb_led_marquee_enable && ledblink1_step != 0) { + if (!g_usb_led_marquee_enable && rgb_marquee_usb_open_sweep_step != 0) { startled = 0; setled = 0; rgb_marquee_stop(); @@ -81,7 +81,7 @@ void ledblink1(uint8_t color, uint8_t dir) { led_pins_arr = hw_get_led_reversal_array(); } - if (ledblink1_step == 0) { + if (rgb_marquee_usb_open_sweep_step == 0) { //Adjust the color set_slot_light_color(color); pwm_sequ_val.channel_0 = 1; @@ -89,13 +89,13 @@ void ledblink1(uint8_t color, uint8_t dir) { pwm_sequ_val.channel_2 = 1; pwm_sequ_val.channel_3 = 1; bsp_set_timer(timer, 0); - ledblink1_step = 1; + rgb_marquee_usb_open_sweep_step = 1; // Reset the state of the light when the USB is turned on to open the communication - ledblink6_step = 0; + rgb_marquee_usb_idle_step = 0; } - if (ledblink1_step == 1) { + if (rgb_marquee_usb_open_sweep_step == 1) { setled = startled; for (uint8_t i = 0; i < 4; i++) { pwm_config.output_pins[i] = led_pins_arr[setled]; @@ -109,12 +109,12 @@ void ledblink1(uint8_t color, uint8_t dir) { nrf_drv_pwm_simple_playback(&pwm0_ins, &seq, 1, NRF_DRV_PWM_FLAG_LOOP); bsp_set_timer(timer, 0); - ledblink1_step = 2; + rgb_marquee_usb_open_sweep_step = 2; } - if (ledblink1_step == 2) { + if (rgb_marquee_usb_open_sweep_step == 2) { if (!(NO_TIMEOUT_1MS(timer, 80))) { - ledblink1_step = 1; + rgb_marquee_usb_open_sweep_step = 1; } } } @@ -122,7 +122,7 @@ void ledblink1(uint8_t color, uint8_t dir) { // 4 Lights Dragon Tail horizontal movement cycle (not returning), including the disappearance of the tail and the head of the head slowly //dir 0-from 1 card slot to 8 card slot, 1-from 8 card slot to 1 card slot (Direction, the end point is determined by the END parameter) //end To scan the number of lamps, decide the final animation area with the direction -void ledblink2(uint8_t color, uint8_t dir, uint8_t end) { +void rgb_marquee_sweep_to(uint8_t color, uint8_t dir, uint8_t end) { uint8_t startled = 0; uint8_t setled = 0; uint8_t leds2turnon = 0; @@ -203,12 +203,12 @@ void ledblink2(uint8_t color, uint8_t dir, uint8_t end) { //led_down LED to be extinguished //color_led_down The color of the LED to be extinguished 0-R,1-G,2-B volatile bool callback_waiting = 0; -static void ledblink3_pwm_callback(nrfx_pwm_evt_type_t event_type) { +static void rgb_marquee_slot_switch_pwm_callback(nrfx_pwm_evt_type_t event_type) { if (event_type == NRF_DRV_PWM_EVT_FINISHED) { callback_waiting = 1; } } -void ledblink3(uint8_t led_down, uint8_t color_led_down, uint8_t led_up, uint8_t color_led_up) { +void rgb_marquee_slot_switch(uint8_t led_down, uint8_t color_led_down, uint8_t led_up, uint8_t color_led_up) { int16_t light_level = 99; //ledBrightnessValue uint32_t *led_pins = hw_get_led_array(); if (led_down >= 0 && led_down <= 7) { @@ -229,7 +229,7 @@ void ledblink3(uint8_t led_down, uint8_t color_led_down, uint8_t led_up, uint8_t set_slot_light_color(color_led_down); - nrf_drv_pwm_init(&pwm0_ins, &pwm_config, ledblink3_pwm_callback); + nrf_drv_pwm_init(&pwm0_ins, &pwm_config, rgb_marquee_slot_switch_pwm_callback); nrf_drv_pwm_simple_playback(&pwm0_ins, &seq, 1, NRF_DRV_PWM_FLAG_LOOP); while (callback_waiting == 0); //Waiting for the output of the PWM module to complete @@ -257,7 +257,7 @@ void ledblink3(uint8_t led_down, uint8_t color_led_down, uint8_t led_up, uint8_t set_slot_light_color(color_led_up); - nrf_drv_pwm_init(&pwm0_ins, &pwm_config, ledblink3_pwm_callback); + nrf_drv_pwm_init(&pwm0_ins, &pwm_config, rgb_marquee_slot_switch_pwm_callback); nrf_drv_pwm_simple_playback(&pwm0_ins, &seq, 1, NRF_DRV_PWM_FLAG_LOOP); while (callback_waiting == 0); //Waiting for the output of the PWM module to complete @@ -272,7 +272,7 @@ void ledblink3(uint8_t led_down, uint8_t color_led_down, uint8_t led_up, uint8_t //dir 0-from 1 card slot to 8 card slot, 1-from 8 card slot to 1 card slot (Direction, the end point is determined by the END parameter) //end To scan the number of lamps, decide the final animation area with the direction //start_light stop_light 0-99 Indicate gradient brightness -void ledblink4(uint8_t color, uint8_t dir, uint8_t end, uint8_t start_light, uint8_t stop_light) { +void rgb_marquee_sweep_fade(uint8_t color, uint8_t dir, uint8_t end, uint8_t start_light, uint8_t stop_light) { uint8_t startled = 0; uint8_t setled = 0; uint8_t leds2turnon = 0; @@ -346,7 +346,7 @@ void ledblink4(uint8_t color, uint8_t dir, uint8_t end, uint8_t start_light, uin //color The color of the lit LED 0-R,1-G,2-B //start Start the lamp position //stop Stop lamp position -void ledblink5(uint8_t color, uint8_t start, uint8_t stop) { +void rgb_marquee_sweep_from_to(uint8_t color, uint8_t start, uint8_t stop) { uint8_t setled = start; uint32_t *led_pins = hw_get_led_array(); //Set the brightness @@ -375,25 +375,25 @@ void ledblink5(uint8_t color, uint8_t start, uint8_t stop) { // Charging animation // the current percentage of the battery 0-4 4 represents full electric breathing light volatile bool callback_waiting6 = 0; -void ledblink6_pwm_callback(nrfx_pwm_evt_type_t event_type) { +void rgb_marquee_usb_idle_pwm_callback(nrfx_pwm_evt_type_t event_type) { if (event_type == NRF_DRV_PWM_EVT_FINISHED) { callback_waiting6 = 1; } } -void ledblink6(void) { +void rgb_marquee_usb_idle(void) { uint32_t *led_array = hw_get_led_array(); const uint16_t delay_time = 25; static int16_t light_level = 99; //LED brightness value - if (!g_usb_led_marquee_enable && ledblink6_step != 0) { + if (!g_usb_led_marquee_enable && rgb_marquee_usb_idle_step != 0) { light_level = 99; callback_waiting6 = 0; rgb_marquee_stop(); return; } - if (ledblink6_step == 0) { - set_slot_light_color(ledblink6_color); + if (rgb_marquee_usb_idle_step == 0) { + set_slot_light_color(rgb_marquee_usb_idle_color); for (uint8_t i = 0; i < RGB_LIST_NUM; i++) { nrf_gpio_pin_clear(led_array[i]); } @@ -401,87 +401,87 @@ void ledblink6(void) { pwm_config.output_pins[1] = led_array[3]; pwm_config.output_pins[2] = led_array[4]; pwm_config.output_pins[3] = led_array[5]; - ledblink6_step = 1; + rgb_marquee_usb_idle_step = 1; // Reset the state of the lamp when the USB is not turned on - ledblink1_step = 0; + rgb_marquee_usb_open_sweep_step = 0; } - if (ledblink6_step == 1) { + if (rgb_marquee_usb_idle_step == 1) { light_level = 0; - ledblink6_step = 2; + rgb_marquee_usb_idle_step = 2; } - if (ledblink6_step == 2 || ledblink6_step == 3 || ledblink6_step == 4) { + if (rgb_marquee_usb_idle_step == 2 || rgb_marquee_usb_idle_step == 3 || rgb_marquee_usb_idle_step == 4) { if (light_level <= 99) { - if (ledblink6_step == 2) { + if (rgb_marquee_usb_idle_step == 2) { //Treatment brightness pwm_sequ_val.channel_0 = get_pwmduty(light_level); pwm_sequ_val.channel_1 = pwm_sequ_val.channel_0; pwm_sequ_val.channel_2 = pwm_sequ_val.channel_0; pwm_sequ_val.channel_3 = pwm_sequ_val.channel_0; nrfx_pwm_uninit(&pwm0_ins); //Close PWM output - set_slot_light_color(ledblink6_color); - nrf_drv_pwm_init(&pwm0_ins, &pwm_config, ledblink6_pwm_callback); + set_slot_light_color(rgb_marquee_usb_idle_color); + nrf_drv_pwm_init(&pwm0_ins, &pwm_config, rgb_marquee_usb_idle_pwm_callback); nrf_drv_pwm_simple_playback(&pwm0_ins, &seq, 1, NRF_DRV_PWM_FLAG_LOOP); - ledblink6_step = 3; + rgb_marquee_usb_idle_step = 3; } - if (ledblink6_step == 3) { //Waiting for the output of the PWM module to complete + if (rgb_marquee_usb_idle_step == 3) { //Waiting for the output of the PWM module to complete if (callback_waiting6 != 0) { - ledblink6_step = 4; + rgb_marquee_usb_idle_step = 4; bsp_set_timer(timer, 0); } } - if (ledblink6_step == 4) { + if (rgb_marquee_usb_idle_step == 4) { if (!NO_TIMEOUT_1MS(timer, delay_time)) { callback_waiting = 0; light_level++; - ledblink6_step = 2; + rgb_marquee_usb_idle_step = 2; } } } else { - ledblink6_step = 5; + rgb_marquee_usb_idle_step = 5; } } - if (ledblink6_step == 5) { + if (rgb_marquee_usb_idle_step == 5) { light_level = 99; - ledblink6_step = 6; + rgb_marquee_usb_idle_step = 6; } - if (ledblink6_step == 6 || ledblink6_step == 7 || ledblink6_step == 8) { + if (rgb_marquee_usb_idle_step == 6 || rgb_marquee_usb_idle_step == 7 || rgb_marquee_usb_idle_step == 8) { if (light_level >= 0) { - if (ledblink6_step == 6) { + if (rgb_marquee_usb_idle_step == 6) { //Treatment brightness pwm_sequ_val.channel_0 = get_pwmduty(light_level); pwm_sequ_val.channel_1 = pwm_sequ_val.channel_0; pwm_sequ_val.channel_2 = pwm_sequ_val.channel_0; pwm_sequ_val.channel_3 = pwm_sequ_val.channel_0; nrfx_pwm_uninit(&pwm0_ins); //Close PWM output - set_slot_light_color(ledblink6_color); - nrf_drv_pwm_init(&pwm0_ins, &pwm_config, ledblink6_pwm_callback); + set_slot_light_color(rgb_marquee_usb_idle_color); + nrf_drv_pwm_init(&pwm0_ins, &pwm_config, rgb_marquee_usb_idle_pwm_callback); nrf_drv_pwm_simple_playback(&pwm0_ins, &seq, 1, NRF_DRV_PWM_FLAG_LOOP); - ledblink6_step = 7; + rgb_marquee_usb_idle_step = 7; } - if (ledblink6_step == 7) { //Waiting for the output of the PWM module to complete + if (rgb_marquee_usb_idle_step == 7) { //Waiting for the output of the PWM module to complete if (callback_waiting6 != 0) { - ledblink6_step = 8; + rgb_marquee_usb_idle_step = 8; bsp_set_timer(timer, 0); } } - if (ledblink6_step == 8) { + if (rgb_marquee_usb_idle_step == 8) { if (!NO_TIMEOUT_1MS(timer, delay_time)) { callback_waiting = 0; light_level--; - ledblink6_step = 6; + rgb_marquee_usb_idle_step = 6; } } } else { - ledblink6_step = 0; - //if (++ledblink6_color == RGB_WHITE) ledblink6_color = RGB_RED; + rgb_marquee_usb_idle_step = 0; + //if (++rgb_marquee_usb_idle_color == RGB_WHITE) rgb_marquee_usb_idle_color = RGB_RED; uint8_t new_color = rand() % 6; - for (; new_color == ledblink6_color; new_color = rand() % 6); - ledblink6_color = new_color; + for (; new_color == rgb_marquee_usb_idle_color; new_color = rand() % 6); + rgb_marquee_usb_idle_color = new_color; } } } @@ -492,6 +492,6 @@ void ledblink6(void) { * @return true Make the state, flickering in the lighting effect * @return false The state is prohibited, in the state of ordinary card slot indicator */ -bool is_rgb_marquee_enable(void) { +bool rgb_marquee_is_enabled(void) { return g_usb_led_marquee_enable; } diff --git a/firmware/application/src/rgb_marquee.h b/firmware/application/src/rgb_marquee.h index edfa70e..b0fab9e 100644 --- a/firmware/application/src/rgb_marquee.h +++ b/firmware/application/src/rgb_marquee.h @@ -8,12 +8,12 @@ void rgb_marquee_init(void); void rgb_marquee_stop(void); void rgb_marquee_reset(void); -bool is_rgb_marquee_enable(void); -void ledblink1(uint8_t color, uint8_t dir); -void ledblink2(uint8_t color, uint8_t dir, uint8_t end); -void ledblink3(uint8_t led_down, uint8_t color_led_down, uint8_t led_up, uint8_t color_led_up); -void ledblink4(uint8_t color, uint8_t dir, uint8_t end, uint8_t start_light, uint8_t stop_light); -void ledblink5(uint8_t color, uint8_t start, uint8_t stop); -void ledblink6(void); +bool rgb_marquee_is_enabled(void); +void rgb_marquee_usb_open_sweep(uint8_t color, uint8_t dir); +void rgb_marquee_sweep_to(uint8_t color, uint8_t dir, uint8_t end); +void rgb_marquee_slot_switch(uint8_t led_down, uint8_t color_led_down, uint8_t led_up, uint8_t color_led_up); +void rgb_marquee_sweep_fade(uint8_t color, uint8_t dir, uint8_t end, uint8_t start_light, uint8_t stop_light); +void rgb_marquee_sweep_from_to(uint8_t color, uint8_t start, uint8_t stop); +void rgb_marquee_usb_idle(void); #endif From 9f25debe4d12e79e14ebf58f7e4b674005bbb152 Mon Sep 17 00:00:00 2001 From: WillyJL Date: Sat, 23 Aug 2025 02:00:33 +0200 Subject: [PATCH 2/5] Fix rgb_marquee_sweep_from_to() to the left --- firmware/application/src/rgb_marquee.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/application/src/rgb_marquee.c b/firmware/application/src/rgb_marquee.c index 341406c..18926b1 100644 --- a/firmware/application/src/rgb_marquee.c +++ b/firmware/application/src/rgb_marquee.c @@ -347,7 +347,7 @@ void rgb_marquee_sweep_fade(uint8_t color, uint8_t dir, uint8_t end, uint8_t sta //start Start the lamp position //stop Stop lamp position void rgb_marquee_sweep_from_to(uint8_t color, uint8_t start, uint8_t stop) { - uint8_t setled = start; + int8_t setled = start; uint32_t *led_pins = hw_get_led_array(); //Set the brightness pwm_sequ_val.channel_3 = 0; @@ -356,7 +356,7 @@ void rgb_marquee_sweep_from_to(uint8_t color, uint8_t start, uint8_t stop) { pwm_sequ_val.channel_0 = get_pwmduty(99); //Adjust the color set_slot_light_color(color); - while (setled < (start < stop ? stop + 1 : stop - 1)) { + while (start < stop ? (setled < stop + 1) : (setled > (int8_t)stop - 1)) { //Close all channels pwm_config.output_pins[0] = NRF_DRV_PWM_PIN_NOT_USED; pwm_config.output_pins[1] = NRF_DRV_PWM_PIN_NOT_USED; From 402665cd750f2c1f42998813c739e9448c30ecd3 Mon Sep 17 00:00:00 2001 From: WillyJL Date: Sat, 23 Aug 2025 02:02:59 +0200 Subject: [PATCH 3/5] Minimal shutdown and post-flash boot animations --- firmware/application/src/app_main.c | 37 ++++++++++++++++++----------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/firmware/application/src/app_main.c b/firmware/application/src/app_main.c index 8d91bac..857b722 100644 --- a/firmware/application/src/app_main.c +++ b/firmware/application/src/app_main.c @@ -301,24 +301,26 @@ static void system_off_enter(void) { for (uint8_t i = 0; i < RGB_LIST_NUM; i++) { nrf_gpio_pin_clear(p_led_array[i]); } + // Power off animation uint8_t animation_config = settings_get_animation_config(); - if (animation_config == SettingsAnimationModeFull) { - uint8_t slot = tag_emulation_get_slot(); - // Power off animation - uint8_t dir = slot > 3 ? 1 : 0; - uint8_t color = get_color_by_slot(slot); - if (m_reset_source & (NRF_POWER_RESETREAS_NFC_MASK | NRF_POWER_RESETREAS_LPCOMP_MASK)) { - if (m_reset_source & NRF_POWER_RESETREAS_NFC_MASK) { - color = 1; - } else { - color = 2; - } + uint8_t slot = tag_emulation_get_slot(); + uint8_t dir = slot > 3 ? 1 : 0; + uint8_t color = get_color_by_slot(slot); + if (m_reset_source & (NRF_POWER_RESETREAS_NFC_MASK | NRF_POWER_RESETREAS_LPCOMP_MASK)) { + if (m_reset_source & NRF_POWER_RESETREAS_NFC_MASK) { + color = 1; + } else { + color = 2; } + } + if (animation_config == SettingsAnimationModeFull) { if (m_system_off_processing) rgb_marquee_sweep_from_to(color, slot, dir ? 7 : 0); if (m_system_off_processing) rgb_marquee_sweep_fade(color, dir, 7, 99, 75); if (m_system_off_processing) rgb_marquee_sweep_fade(color, !dir, 7, 75, 50); if (m_system_off_processing) rgb_marquee_sweep_fade(color, dir, 7, 50, 25); if (m_system_off_processing) rgb_marquee_sweep_fade(color, !dir, 7, 25, 0); + } else if (animation_config == SettingsAnimationModeMinimal) { + if (m_system_off_processing) rgb_marquee_sweep_from_to(color, slot, !dir ? 7 : 0); } rgb_marquee_stop(); if (!m_system_off_processing) { @@ -526,9 +528,16 @@ static void check_wakeup_src(void) { tag_emulation_factory_init(); // RGB - rgb_marquee_sweep_to(0, !dir, 11); - rgb_marquee_sweep_to(1, dir, 11); - rgb_marquee_sweep_to(2, !dir, 11); + uint8_t animation_config = settings_get_animation_config(); + if (animation_config == SettingsAnimationModeFull) { + rgb_marquee_sweep_to(0, !dir, 11); + rgb_marquee_sweep_to(1, dir, 11); + rgb_marquee_sweep_to(2, !dir, 11); + } else if (animation_config == SettingsAnimationModeMinimal) { + rgb_marquee_sweep_from_to(0, 0, 2); + rgb_marquee_sweep_from_to(1, 2, 5); + rgb_marquee_sweep_from_to(2, 5, 7); + } // Show RGB for slot. set_slot_light_color(color); From 4bafe186b33601df54d1bc4c8f8dc47025702968 Mon Sep 17 00:00:00 2001 From: WillyJL Date: Sat, 23 Aug 2025 02:47:04 +0200 Subject: [PATCH 4/5] Symmetric animation mode for boot, shutdown, usb --- firmware/application/src/app_cmd.c | 2 +- firmware/application/src/app_main.c | 20 ++- firmware/application/src/rgb_marquee.c | 191 +++++++++++++++++++++++-- firmware/application/src/rgb_marquee.h | 3 + firmware/application/src/settings.h | 2 + software/script/chameleon_enum.py | 3 + 6 files changed, 207 insertions(+), 14 deletions(-) diff --git a/firmware/application/src/app_cmd.c b/firmware/application/src/app_cmd.c index a0ecb22..4e920cc 100644 --- a/firmware/application/src/app_cmd.c +++ b/firmware/application/src/app_cmd.c @@ -141,7 +141,7 @@ static data_frame_tx_t *cmd_processor_get_device_settings(uint16_t cmd, uint16_t } static data_frame_tx_t *cmd_processor_set_animation_mode(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { - if ((length != 1) || (data[0] > 2)) { + if ((length != 1) || (data[0] >= SettingsAnimationModeMAX)) { return data_frame_make(cmd, STATUS_PAR_ERR, 0, NULL); } settings_set_animation_config(data[0]); diff --git a/firmware/application/src/app_main.c b/firmware/application/src/app_main.c index 857b722..6f8a56e 100644 --- a/firmware/application/src/app_main.c +++ b/firmware/application/src/app_main.c @@ -321,6 +321,8 @@ static void system_off_enter(void) { if (m_system_off_processing) rgb_marquee_sweep_fade(color, !dir, 7, 25, 0); } else if (animation_config == SettingsAnimationModeMinimal) { if (m_system_off_processing) rgb_marquee_sweep_from_to(color, slot, !dir ? 7 : 0); + } else if (animation_config == SettingsAnimationModeSymmetric) { + if (m_system_off_processing) rgb_marquee_symmetric_in(color, slot); } rgb_marquee_stop(); if (!m_system_off_processing) { @@ -467,6 +469,8 @@ static void check_wakeup_src(void) { rgb_marquee_sweep_to(color, !dir, dir ? slot : 7 - slot); } else if (animation_config == SettingsAnimationModeMinimal) { rgb_marquee_sweep_to(color, !dir, dir ? slot : 7 - slot); + } else if (animation_config == SettingsAnimationModeSymmetric) { + rgb_marquee_symmetric_out(color, slot); } else { set_slot_light_color(color); } @@ -500,8 +504,11 @@ static void check_wakeup_src(void) { if (animation_config == SettingsAnimationModeFull) { // In the case of field wake-up, only one round of RGB is swept as the power-on animation rgb_marquee_sweep_to(color, !dir, dir ? slot : 7 - slot); + } else if (animation_config == SettingsAnimationModeSymmetric) { + rgb_marquee_symmetric_out(color, slot); + } else { + set_slot_light_color(color); } - set_slot_light_color(color); light_up_by_slot(); // We can only run tag emulation at field wakeup source. @@ -537,6 +544,10 @@ static void check_wakeup_src(void) { rgb_marquee_sweep_from_to(0, 0, 2); rgb_marquee_sweep_from_to(1, 2, 5); rgb_marquee_sweep_from_to(2, 5, 7); + } else if (animation_config == SettingsAnimationModeSymmetric) { + rgb_marquee_symmetric_out(0, ~0); + rgb_marquee_symmetric_in(1, ~0); + rgb_marquee_symmetric_out(2, ~0); } // Show RGB for slot. @@ -936,7 +947,12 @@ static void blink_usb_led_status(void) { if (rgb_marquee_is_enabled()) { is_working = true; if (g_usb_port_opened) { - rgb_marquee_usb_open_sweep(color, dir); + uint8_t animation_config = settings_get_animation_config(); + if (animation_config == SettingsAnimationModeSymmetric) { + rgb_marquee_usb_open_symmetric(color); + } else { + rgb_marquee_usb_open_sweep(color, dir); + } } else { rgb_marquee_usb_idle(); } diff --git a/firmware/application/src/rgb_marquee.c b/firmware/application/src/rgb_marquee.c index 18926b1..1705de0 100644 --- a/firmware/application/src/rgb_marquee.c +++ b/firmware/application/src/rgb_marquee.c @@ -34,7 +34,7 @@ nrf_drv_pwm_config_t pwm_config = {//PWM configuration structure static autotimer *timer; static uint8_t rgb_marquee_usb_idle_step = 0; static uint8_t rgb_marquee_usb_idle_color = RGB_RED; -static uint8_t rgb_marquee_usb_open_sweep_step = 0; +static uint8_t rgb_marquee_usb_open_step = 0; extern bool g_usb_led_marquee_enable; @@ -46,13 +46,13 @@ void rgb_marquee_stop(void) { nrfx_pwm_stop(&pwm0_ins, true); nrfx_pwm_uninit(&pwm0_ins);//turn off pwm output rgb_marquee_usb_idle_step = 0; - rgb_marquee_usb_open_sweep_step = 0; + rgb_marquee_usb_open_step = 0; } // reset RGB state machines to force a refresh of the LED color void rgb_marquee_reset(void) { rgb_marquee_usb_idle_step = 0; - rgb_marquee_usb_open_sweep_step = 0; + rgb_marquee_usb_open_step = 0; } // Brightness to PWM value @@ -67,7 +67,7 @@ void rgb_marquee_usb_open_sweep(uint8_t color, uint8_t dir) { static uint8_t setled = 0; uint32_t *led_pins_arr; - if (!g_usb_led_marquee_enable && rgb_marquee_usb_open_sweep_step != 0) { + if (!g_usb_led_marquee_enable && rgb_marquee_usb_open_step != 0) { startled = 0; setled = 0; rgb_marquee_stop(); @@ -81,7 +81,7 @@ void rgb_marquee_usb_open_sweep(uint8_t color, uint8_t dir) { led_pins_arr = hw_get_led_reversal_array(); } - if (rgb_marquee_usb_open_sweep_step == 0) { + if (rgb_marquee_usb_open_step == 0) { //Adjust the color set_slot_light_color(color); pwm_sequ_val.channel_0 = 1; @@ -89,13 +89,13 @@ void rgb_marquee_usb_open_sweep(uint8_t color, uint8_t dir) { pwm_sequ_val.channel_2 = 1; pwm_sequ_val.channel_3 = 1; bsp_set_timer(timer, 0); - rgb_marquee_usb_open_sweep_step = 1; + rgb_marquee_usb_open_step = 1; // Reset the state of the light when the USB is turned on to open the communication rgb_marquee_usb_idle_step = 0; } - if (rgb_marquee_usb_open_sweep_step == 1) { + if (rgb_marquee_usb_open_step == 1) { setled = startled; for (uint8_t i = 0; i < 4; i++) { pwm_config.output_pins[i] = led_pins_arr[setled]; @@ -109,12 +109,61 @@ void rgb_marquee_usb_open_sweep(uint8_t color, uint8_t dir) { nrf_drv_pwm_simple_playback(&pwm0_ins, &seq, 1, NRF_DRV_PWM_FLAG_LOOP); bsp_set_timer(timer, 0); - rgb_marquee_usb_open_sweep_step = 2; + rgb_marquee_usb_open_step = 2; } - if (rgb_marquee_usb_open_sweep_step == 2) { + if (rgb_marquee_usb_open_step == 2) { if (!(NO_TIMEOUT_1MS(timer, 80))) { - rgb_marquee_usb_open_sweep_step = 1; + rgb_marquee_usb_open_step = 1; + } + } +} + +void rgb_marquee_usb_open_symmetric(uint8_t color) { + static uint8_t startled = 0; + static uint8_t setled = 0; + uint32_t *led_pins_arr = hw_get_led_array(); + + if (!g_usb_led_marquee_enable && rgb_marquee_usb_open_step != 0) { + startled = 0; + setled = 0; + rgb_marquee_stop(); + return; + } + + if (rgb_marquee_usb_open_step == 0) { + //Adjust the color + set_slot_light_color(color); + pwm_sequ_val.channel_0 = 1; + pwm_sequ_val.channel_1 = 1; + pwm_sequ_val.channel_2 = 1; + pwm_sequ_val.channel_3 = 1; + bsp_set_timer(timer, 0); + rgb_marquee_usb_open_step = 1; + + // Reset the state of the light when the USB is turned on to open the communication + rgb_marquee_usb_idle_step = 0; + } + + if (rgb_marquee_usb_open_step == 1) { + setled = startled < 4 ? startled : (4 - (startled - 3)); + pwm_config.output_pins[0] = led_pins_arr[setled]; + pwm_config.output_pins[1] = led_pins_arr[7 - setled]; + pwm_config.output_pins[2] = NRF_DRV_PWM_PIN_NOT_USED; + pwm_config.output_pins[3] = NRF_DRV_PWM_PIN_NOT_USED; + startled++; + if (startled > 7)startled = 0; + nrfx_pwm_uninit(&pwm0_ins); + nrf_drv_pwm_init(&pwm0_ins, &pwm_config, NULL); + nrf_drv_pwm_simple_playback(&pwm0_ins, &seq, 1, NRF_DRV_PWM_FLAG_LOOP); + + bsp_set_timer(timer, 0); + rgb_marquee_usb_open_step = 2; + } + + if (rgb_marquee_usb_open_step == 2) { + if (!(NO_TIMEOUT_1MS(timer, 100))) { + rgb_marquee_usb_open_step = 1; } } } @@ -404,7 +453,7 @@ void rgb_marquee_usb_idle(void) { rgb_marquee_usb_idle_step = 1; // Reset the state of the lamp when the USB is not turned on - rgb_marquee_usb_open_sweep_step = 0; + rgb_marquee_usb_open_step = 0; } if (rgb_marquee_usb_idle_step == 1) { @@ -486,6 +535,126 @@ void rgb_marquee_usb_idle(void) { } } +void rgb_marquee_symmetric_out(uint8_t color, uint8_t slot) { + uint32_t *led_pins = hw_get_led_array(); + + //Adjust the color + set_slot_light_color(color); + pwm_sequ_val.channel_3 = 950; + pwm_sequ_val.channel_2 = 770; + pwm_sequ_val.channel_1 = 770; + pwm_sequ_val.channel_0 = 950; + + const uint8_t half_leds = 4; + const uint8_t slide_leds = 2; + const uint8_t solid_leds = 6; + for (uint8_t step = 0; step < slide_leds + solid_leds + half_leds + slide_leds; step++) { + //Close all channels + pwm_config.output_pins[0] = NRF_DRV_PWM_PIN_NOT_USED; + pwm_config.output_pins[1] = NRF_DRV_PWM_PIN_NOT_USED; + pwm_config.output_pins[2] = NRF_DRV_PWM_PIN_NOT_USED; + pwm_config.output_pins[3] = NRF_DRV_PWM_PIN_NOT_USED; + for (uint8_t i = 0; i < RGB_LIST_NUM; i++) { + nrf_gpio_pin_clear(led_pins[i]); + } + + const uint8_t length = slide_leds + solid_leds + slide_leds; + for (uint8_t offset = 0; offset < length; offset++) { + if (step < offset || step >= (offset + half_leds)) continue; + switch (offset) { + case 0: + case length - 1: + pwm_config.output_pins[0] = led_pins[3 - step + offset]; + pwm_config.output_pins[3] = led_pins[4 + step - offset]; + break; + case 1: + case length - 2: + pwm_config.output_pins[1] = led_pins[3 - step + offset]; + pwm_config.output_pins[2] = led_pins[4 + step - offset]; + break; + default: + nrf_gpio_pin_set(led_pins[3 - step + offset]); + nrf_gpio_pin_set(led_pins[4 + step - offset]); + } + } + + if ((slot <= 3 && slot > (3 - step + slide_leds)) || + (slot >= 4 && slot < (4 + step - slide_leds))) { + nrf_gpio_pin_set(led_pins[slot]); + for (uint8_t j = 0; j < 4; j++) { + if (pwm_config.output_pins[j] == led_pins[slot]) { + pwm_config.output_pins[j] = NRF_DRV_PWM_PIN_NOT_USED; + } + } + } + + nrfx_pwm_uninit(&pwm0_ins); + nrf_drv_pwm_init(&pwm0_ins, &pwm_config, NULL); + nrf_drv_pwm_simple_playback(&pwm0_ins, &seq, 1, NRF_DRV_PWM_FLAG_LOOP); + bsp_delay_ms(60); + } +} + +void rgb_marquee_symmetric_in(uint8_t color, uint8_t slot) { + uint32_t *led_pins = hw_get_led_array(); + + //Adjust the color + set_slot_light_color(color); + pwm_sequ_val.channel_3 = 950; + pwm_sequ_val.channel_2 = 770; + pwm_sequ_val.channel_1 = 770; + pwm_sequ_val.channel_0 = 950; + + const uint8_t half_leds = 4; + const uint8_t slide_leds = 2; + const uint8_t solid_leds = 6; + for (uint8_t step = 0; step < slide_leds + solid_leds + half_leds + slide_leds; step++) { + //Close all channels + pwm_config.output_pins[0] = NRF_DRV_PWM_PIN_NOT_USED; + pwm_config.output_pins[1] = NRF_DRV_PWM_PIN_NOT_USED; + pwm_config.output_pins[2] = NRF_DRV_PWM_PIN_NOT_USED; + pwm_config.output_pins[3] = NRF_DRV_PWM_PIN_NOT_USED; + for (uint8_t i = 0; i < RGB_LIST_NUM; i++) { + nrf_gpio_pin_clear(led_pins[i]); + } + + const uint8_t length = slide_leds + solid_leds + slide_leds; + for (uint8_t offset = 0; offset < length; offset++) { + if (step < offset || step >= (offset + half_leds)) continue; + switch (offset) { + case 0: + case length - 1: + pwm_config.output_pins[0] = led_pins[0 + step - offset]; + pwm_config.output_pins[3] = led_pins[7 - step + offset]; + break; + case 1: + case length - 2: + pwm_config.output_pins[1] = led_pins[0 + step - offset]; + pwm_config.output_pins[2] = led_pins[7 - step + offset]; + break; + default: + nrf_gpio_pin_set(led_pins[0 + step - offset]); + nrf_gpio_pin_set(led_pins[7 - step + offset]); + } + } + + if ((slot <= 3 && slot > (0 + step - slide_leds)) || + (slot >= 4 && slot < (7 - step + slide_leds))) { + nrf_gpio_pin_set(led_pins[slot]); + for (uint8_t j = 0; j < 4; j++) { + if (pwm_config.output_pins[j] == led_pins[slot]) { + pwm_config.output_pins[j] = NRF_DRV_PWM_PIN_NOT_USED; + } + } + } + + nrfx_pwm_uninit(&pwm0_ins); + nrf_drv_pwm_init(&pwm0_ins, &pwm_config, NULL); + nrf_drv_pwm_simple_playback(&pwm0_ins, &seq, 1, NRF_DRV_PWM_FLAG_LOOP); + bsp_delay_ms(60); + } +} + /** * @brief Whether the current lighting effect enables * diff --git a/firmware/application/src/rgb_marquee.h b/firmware/application/src/rgb_marquee.h index b0fab9e..ca3ad3e 100644 --- a/firmware/application/src/rgb_marquee.h +++ b/firmware/application/src/rgb_marquee.h @@ -10,10 +10,13 @@ void rgb_marquee_stop(void); void rgb_marquee_reset(void); bool rgb_marquee_is_enabled(void); void rgb_marquee_usb_open_sweep(uint8_t color, uint8_t dir); +void rgb_marquee_usb_open_symmetric(uint8_t color); void rgb_marquee_sweep_to(uint8_t color, uint8_t dir, uint8_t end); void rgb_marquee_slot_switch(uint8_t led_down, uint8_t color_led_down, uint8_t led_up, uint8_t color_led_up); void rgb_marquee_sweep_fade(uint8_t color, uint8_t dir, uint8_t end, uint8_t start_light, uint8_t stop_light); void rgb_marquee_sweep_from_to(uint8_t color, uint8_t start, uint8_t stop); void rgb_marquee_usb_idle(void); +void rgb_marquee_symmetric_out(uint8_t color, uint8_t slot); +void rgb_marquee_symmetric_in(uint8_t color, uint8_t slot); #endif diff --git a/firmware/application/src/settings.h b/firmware/application/src/settings.h index a690ea4..cd8baf3 100644 --- a/firmware/application/src/settings.h +++ b/firmware/application/src/settings.h @@ -12,7 +12,9 @@ typedef enum { SettingsAnimationModeFull = 0U, SettingsAnimationModeMinimal = 1U, + SettingsAnimationModeSymmetric = 3U, SettingsAnimationModeNone = 2U, + SettingsAnimationModeMAX = 4U, } settings_animation_mode_t; typedef enum { diff --git a/software/script/chameleon_enum.py b/software/script/chameleon_enum.py index 890b1aa..404c8c0 100644 --- a/software/script/chameleon_enum.py +++ b/software/script/chameleon_enum.py @@ -513,6 +513,7 @@ class MifareClassicDarksideStatus(enum.IntEnum): class AnimationMode(enum.IntEnum): FULL = 0 MINIMAL = 1 + SYMMETRIC = 3 NONE = 2 def __str__(self): @@ -520,6 +521,8 @@ class AnimationMode(enum.IntEnum): return "Full animation" elif self == AnimationMode.MINIMAL: return "Minimal animation" + elif self == AnimationMode.SYMMETRIC: + return "Symmetric animation" elif self == AnimationMode.NONE: return "No animation" From 24259f78b95348f2bc7fdcd29b1874e9709b15aa Mon Sep 17 00:00:00 2001 From: WillyJL Date: Wed, 18 Feb 2026 20:58:33 +0100 Subject: [PATCH 5/5] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71eeaa9..b198c8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added cmd for set mf1 config 'field_off_do_reset' (@xianglin1998) - Fix Windows build (@suut) - Added `hf 14a config` to deal with badly configured cards (@azuwis) + - New Symmetrical LED Animation Mode and Improved Minimal Mode (@WillyJL) ## [v2.1.0][2025-09-02] - Added UV, formatter and linter. Contribution guidelines. (@GameTec-live)