T_LL_KEY_EVT tKeyEvt;
char string[32];



//// State Machine
//#define     state_JUST_WAKE_UP                                  0
//#define     state_WAIT_FOR_THE_POSSIBLE_BUTTON_EVENT            1
//#define     state_WAIT_FOR_THE_POSSIBLE_LONG_PRESS_OF_POWER_ON  2
//#define     state_FADE_ON                                       3
//#define     state_ON_1st_3S_FOR_POSSIBLE_LONG_PRESS_OF_PAIRING  4
//#define     state_ON                                            5
//#define     state_PAIRING                                       6
//#define     state_FADE_OFF                                      7
//#define     state_SLEEP                                         8
//val_0to255  state = state_JUST_WAKE_UP;
//
// a main timer for State Machine
val_timestamp timestamp_StateMachine;
//
// a frequently used function
#define state_ChangeTo(new_state)   timestamp_StateMachine = CLOCK_ms; state = new_state;



// mode
val_0to255  mode;
val_0to255  mode_for_prototype = 1; // 1: as default when Power On
#define modeSwitchToNext    mode++; if(mode > 3) { /* if out of range */ mode = 1; /* cycle back to Mode 1 */ };    mode_for_prototype++; if(mode_for_prototype > 4) { mode_for_prototype = 1; }
//
val_0to255 prev_mode_of_Front = 0;
val_0to255 prev_mode_of_Rear = 0; 
val_0to255 prev_mode_for_prototype = 0;

static int After_Pairing_Flag = 0; // 1:after pairing flag


// Fade On/Off when Power On/Off
//
// Requirement:
// 1) Different light for different Profile.
// 2) The Target/Initial Brightness of Fade On/Off should be the user setting one, not 100/0.
// 3) The total duration should be fixed (now it is 1s), which means the step duration is variable acc to the user setting brightness.
//////
////E_LL_PWM fade_onoff_light(void) { // the light for fade on/off
////    if(Profile_ON == getCustomizedSetting(Profiles[Profile_Front])) { return E_LL_PWM_FRONT_WHITE;  }
////    if(Profile_ON == getCustomizedSetting(Profiles[Profile_Rear ])) { return E_LL_PWM_FRONT_RED;    }
////    return E_LL_LED_PCB_B;//E_LL_PWM_FRONT_YELLOW; // else Profile L/R
////}
//
val_0to255 fade_onoff_brightness_initial;
val_0to255 fade_onoff_brightness_current;
val_0to255 fade_onoff_brightness_target;
//
#define FADE_ONOFF_TOTAL_DURATION   1000    // ms
val_timestamp fade_onoff_step_ms; // the step duration of brightness increase/decrease
val_timestamp fade_onoff_previous;
// 
//#define fade_on_init    brightness_for_fade_on_off = 0;
//#define fade_off_init   fade_onoff_brightness_current = 100;
void fade_onoff_init(unsigned long brightness_initial, unsigned long brightness_target) {
    fade_onoff_brightness_initial = brightness_initial;
    fade_onoff_brightness_target  = brightness_target;//gtPara.brightness[gtPara.eModeOfWarningLight];
    //
    unsigned long brightness_difference;
    if (fade_onoff_brightness_target > fade_onoff_brightness_initial) {
        brightness_difference = fade_onoff_brightness_target - fade_onoff_brightness_initial;
    } else if (fade_onoff_brightness_target < fade_onoff_brightness_initial) {
        brightness_difference = fade_onoff_brightness_initial - fade_onoff_brightness_target;
    } else { // same
        brightness_difference = 1; // 1: avoid 0
    }
    //
    fade_onoff_step_ms = FADE_ONOFF_TOTAL_DURATION / brightness_difference; if(0 == fade_onoff_step_ms) { fade_onoff_step_ms = 10; } // avoid 0
    fade_onoff_brightness_current = fade_onoff_brightness_initial;
}
//
//#define fade_on_loop    fade_onoff_brightness_current += 1; if(fade_onoff_brightness_current < 100) { /* if not 100% yet */ LL_Brightness_set(E_LL_PWM_FRONT_WHITE, fade_onoff_brightness_current); LL_LED_ON(E_LL_PWM_FRONT_WHITE); }
//#define fade_off_loop   fade_onoff_brightness_current -= 1; if(fade_onoff_brightness_current >   0) { /* if not   0% yet */ LL_Brightness_set(E_LL_PWM_FRONT_WHITE, fade_onoff_brightness_current); LL_LED_ON(E_LL_PWM_FRONT_WHITE); }
void fade_onoff_loop(void) {
    if(LL_Timer_Elapsed_ms(fade_onoff_previous) < fade_onoff_step_ms ) return; fade_onoff_previous = CLOCK_ms; // step timeout
    if(fade_onoff_brightness_current == fade_onoff_brightness_target) return; // done
    //
    if(      fade_onoff_brightness_current <  fade_onoff_brightness_target) { fade_onoff_brightness_current += 1; }
    else if( fade_onoff_brightness_current >  fade_onoff_brightness_target) { fade_onoff_brightness_current -= 1; }
    else { /* same, should not happen here */ }
    //
    {
        //E_LL_PWM led = fade_onoff_light();
        //LL_Brightness_set(led, fade_onoff_brightness_current); LL_LED_ON(led); 
        if(Profile_ON == getCustomizedSetting(Profiles[Profile_Front])) {
            LL_Brightness_set(E_LL_PWM_FRONT_WHITE, fade_onoff_brightness_current); LL_LED_ON(E_LL_PWM_FRONT_WHITE); 
        } else if(Profile_ON == getCustomizedSetting(Profiles[Profile_Rear ])) {
//            LL_Brightness_set(E_LL_PWM_RED1, fade_onoff_brightness_current); LL_LED_ON(E_LL_PWM_RED1); 
//            LL_Brightness_set(E_LL_PWM_RED2, fade_onoff_brightness_current); LL_LED_ON(E_LL_PWM_RED2); 
            LL_Brightness_set(E_LL_PWM_FRONT_RED, fade_onoff_brightness_current); LL_LED_ON(E_LL_PWM_FRONT_RED); 
        } else { // else Profile L/R
            LL_Brightness_set(E_LL_PWM_FRONT_YELLOW, fade_onoff_brightness_current); LL_LED_ON(E_LL_PWM_FRONT_YELLOW); 
        }
    }
}



// turning and braking
//
#define LL_TURNING_NO  	 		0
#define LL_TURNING_L   		  1
#define LL_TURNING_R    		2
#define LL_EMERGENCY_FLASH  3
val_0to255  turning = LL_TURNING_NO;
val_0to255  turning_prev = LL_TURNING_NO;
//
#define LL_BRAKING_NO   0
#define LL_BRAKING_YES  1
val_0to255  braking = LL_BRAKING_NO;
val_0to255  braking_prev = LL_BRAKING_NO;
//
void message_handle_of_turning_and_braking(void) {
    if((turning != turning_prev) || (braking != braking_prev)) { turning_prev = turning; braking_prev = braking; // if any change
    } else { return; }
    
    // turning has higher priority than braking
    if(turning != LL_TURNING_NO) { // if turning
				if( turning == LL_EMERGENCY_FLASH ){
						// light all off
						LL_LED_OFF(E_LL_PWM_FRONT_WHITE);
						LL_LED_OFF(E_LL_PWM_FRONT_RED);
						LL_LED_OFF(E_LL_PWM_RED1);
						LL_LED_OFF(E_LL_PWM_RED2);		
						LL_LED_OFF(E_LL_LED_PCB_R);
						LL_LED_OFF(E_LL_LED_PCB_G);							
						LL_LED_OFF(E_LL_LED_PCB_B);

						// light Yellow
            LL_Brightness_set(E_LL_PWM_FRONT_YELLOW, 100); LL_LED_Flashing(E_LL_PWM_FRONT_YELLOW, LL_LED_TURN_FLASH_ON, LL_LED_TURN_FLASH_OFF);					
        }else if( (turning == LL_TURNING_L) && (getCustomizedSetting(Profiles[Profile_L]) == Profile_ON)
        ||  (turning == LL_TURNING_R) && (getCustomizedSetting(Profiles[Profile_R]) == Profile_ON) ) { // if turning direction meets my profile (need a turning animation)
            //
            // light Yellow
            LL_Brightness_set(E_LL_PWM_FRONT_YELLOW, 100); LL_LED_Flashing(E_LL_PWM_FRONT_YELLOW, LL_LED_TURN_FLASH_ON, LL_LED_TURN_FLASH_OFF);
            //
            // turning off other lights to highlight the turning
            // 1) light for Profile L/R (Blue)
            if( (getCustomizedSetting(Profiles[Profile_L]) == Profile_ON)
            ||  (getCustomizedSetting(Profiles[Profile_R]) == Profile_ON) ) {
                LL_LED_OFF(E_LL_LED_PCB_R);
								LL_LED_OFF(E_LL_LED_PCB_G);	
            }
            // 2) light for Profile Front (White)
            if(getCustomizedSetting(Profiles[Profile_Front]) == Profile_ON) {
                LL_LED_OFF(E_LL_PWM_FRONT_WHITE);
            }
            // 3) light for Profile Rear (Red)
            if(getCustomizedSetting(Profiles[Profile_Rear]) == Profile_ON) {
                LL_LED_OFF(E_LL_PWM_FRONT_RED);
                LL_LED_OFF(E_LL_PWM_RED1);
                LL_LED_OFF(E_LL_PWM_RED2);
            }
        } else { // else, this turning is not mine (no need turning animation but need solid my light to highlight others' turning)
            //
            // light Yellow
            LL_LED_OFF(E_LL_PWM_FRONT_YELLOW);
            //
            // solid my light to highlight others' turning
            unsigned long brightness_of_current_mode = gtPara.brightness[gtPara.eModeOfWarningLight];
            // 1) light for Profile L/R (Orange)
            if( (getCustomizedSetting(Profiles[Profile_L]) == Profile_ON)
            ||  (getCustomizedSetting(Profiles[Profile_R]) == Profile_ON) ) {
                //LL_Brightness_set(E_LL_LED_PCB_B, brightness_of_current_mode); LL_LED_ON(E_LL_LED_PCB_B); 
								LL_Brightness_set(E_LL_LED_PCB_R, 100); LL_LED_ON(E_LL_LED_PCB_R); 
								LL_Brightness_set(E_LL_LED_PCB_G, 25); LL_LED_ON(E_LL_LED_PCB_G); 
            }
            // 2) light for Profile Front (White)
            if(getCustomizedSetting(Profiles[Profile_Front]) == Profile_ON) {
                LL_Brightness_set(E_LL_PWM_FRONT_WHITE, brightness_of_current_mode); LL_LED_ON(E_LL_PWM_FRONT_WHITE);
            }
            // 3) light for Profile Rear (Red)
            if(getCustomizedSetting(Profiles[Profile_Rear]) == Profile_ON) {
                LL_Brightness_set(E_LL_PWM_FRONT_RED, brightness_of_current_mode); LL_LED_ON(E_LL_PWM_FRONT_RED);
                LL_LED_OFF(E_LL_PWM_RED1);
                LL_LED_OFF(E_LL_PWM_RED2);
            }            
        }
    } else { // else, no turning (can handle the lower priority braking)
        //
        // light Yellow
        LL_LED_OFF(E_LL_PWM_FRONT_YELLOW);
        //
        if(braking == LL_BRAKING_YES) { // if braking
            if((the_current_profile_support_braking()) && (1 == gtPara.ulBrakeFunction)) { // if braking feature is enabled
                if(1) { //(getCustomizedSetting(Profiles[Profile_Rear]) == Profile_ON) { // if my profile contains Rear (need a braking animation)
                    //
                    #if 0 // braking animation acc to Mode
                    {
                        // braking animation, acc to JIRA task: https://lumoshelmet.atlassian.net/browse/LF-5?atlOrigin=eyJpIjoiZTcyZmMyOTE4ZGU4NGNjNzlkNGUyMTQ2NmI5YzFmMjYiLCJwIjoiaiJ9
                        //  Brake effect in Mode 1: COB solid at max brightness, fast flash dual LEDs
                        //  Brake effect in Mode 2: COB and dual LEDs flashing at max brightness
                        //  Brake effect in Mode 3: COB solid at max brightness, fast flash dual LEDs + turn signal LED                
                        switch(gtPara.eModeOfWarningLight) {
                            case E_MODE_OF_WARNING_LIGHT__Mode1: {
                                //
                                // lights for braking (dual LEDs, also yellow)
                                LL_Brightness_set(E_LL_PWM_RED1, 100); LL_LED_Flashing(E_LL_PWM_RED1, LL_LED_BACK_FAST_FLASH_ON, LL_LED_BACK_FAST_FLASH_OFF);
                                LL_Brightness_set(E_LL_PWM_RED2, 100); LL_LED_Flashing(E_LL_PWM_RED2, LL_LED_BACK_FAST_FLASH_ON, LL_LED_BACK_FAST_FLASH_OFF);
                                LL_LED_OFF(E_LL_PWM_FRONT_YELLOW);
                                //
                                // other lights
                                // 1) light for Profile L/R (Blue)
                                if( (getCustomizedSetting(Profiles[Profile_L]) == Profile_ON)
                                ||  (getCustomizedSetting(Profiles[Profile_R]) == Profile_ON) ) {
                                    LL_LED_OFF(E_LL_LED_PCB_B);
                                }
                                // 2) light for Profile Front (White)
                                if(getCustomizedSetting(Profiles[Profile_Front]) == Profile_ON) {
                                    LL_Brightness_set(E_LL_PWM_FRONT_WHITE, 100); LL_LED_ON(E_LL_PWM_FRONT_WHITE);
                                }
                                // 3) light for Profile Rear (Red)                        
                                if(getCustomizedSetting(Profiles[Profile_Rear]) == Profile_ON) {
                                    LL_Brightness_set(E_LL_PWM_FRONT_RED, 100); LL_LED_ON(E_LL_PWM_FRONT_RED);
                                }            
                            } break;
                            case E_MODE_OF_WARNING_LIGHT__Mode2: {
                                //
                                // lights for braking (dual LEDs, also yellow)
                                LL_Brightness_set(E_LL_PWM_RED1, 100); LL_LED_Flashing(E_LL_PWM_RED1, LL_LED_BACK_FAST_FLASH_ON, LL_LED_BACK_FAST_FLASH_OFF);
                                LL_Brightness_set(E_LL_PWM_RED2, 100); LL_LED_Flashing(E_LL_PWM_RED2, LL_LED_BACK_FAST_FLASH_ON, LL_LED_BACK_FAST_FLASH_OFF);
                                LL_LED_OFF(E_LL_PWM_FRONT_YELLOW);
                                //
                                // other lights
                                // 1) light for Profile L/R (Blue)
                                if( (getCustomizedSetting(Profiles[Profile_L]) == Profile_ON)
                                ||  (getCustomizedSetting(Profiles[Profile_R]) == Profile_ON) ) {
                                    LL_LED_OFF(E_LL_LED_PCB_B);
                                }
                                // 2) light for Profile Front (White)
                                if(getCustomizedSetting(Profiles[Profile_Front]) == Profile_ON) {
                                    LL_Brightness_set(E_LL_PWM_FRONT_WHITE, 100); LL_LED_Flashing(E_LL_PWM_FRONT_WHITE, LL_LED_BACK_FAST_FLASH_ON, LL_LED_BACK_FAST_FLASH_OFF);
                                }
                                // 3) light for Profile Rear (Red)                        
                                if(getCustomizedSetting(Profiles[Profile_Rear]) == Profile_ON) {
                                    LL_Brightness_set(E_LL_PWM_FRONT_RED, 100); LL_LED_Flashing(E_LL_PWM_FRONT_RED, LL_LED_BACK_FAST_FLASH_ON, LL_LED_BACK_FAST_FLASH_OFF);
                                }            
                            } break;
                            case E_MODE_OF_WARNING_LIGHT__Mode3: {
                                //
                                // lights for braking (dual LEDs, also yellow)
                                LL_Brightness_set(E_LL_PWM_RED1,         100); LL_LED_Flashing(E_LL_PWM_RED1,         LL_LED_BACK_FAST_FLASH_ON, LL_LED_BACK_FAST_FLASH_OFF);
                                LL_Brightness_set(E_LL_PWM_RED2,         100); LL_LED_Flashing(E_LL_PWM_RED2,         LL_LED_BACK_FAST_FLASH_ON, LL_LED_BACK_FAST_FLASH_OFF);
                                LL_Brightness_set(E_LL_PWM_FRONT_YELLOW, 100); LL_LED_Flashing(E_LL_PWM_FRONT_YELLOW, LL_LED_BACK_FAST_FLASH_ON, LL_LED_BACK_FAST_FLASH_OFF);
                                //
                                // other lights
                                // 1) light for Profile L/R (Blue)
                                if( (getCustomizedSetting(Profiles[Profile_L]) == Profile_ON)
                                ||  (getCustomizedSetting(Profiles[Profile_R]) == Profile_ON) ) {
                                    LL_LED_OFF(E_LL_LED_PCB_B);
                                }
                                // 2) light for Profile Front (White)
                                if(getCustomizedSetting(Profiles[Profile_Front]) == Profile_ON) {
                                    LL_Brightness_set(E_LL_PWM_FRONT_WHITE, 100); LL_LED_ON(E_LL_PWM_FRONT_WHITE);
                                }
                                // 3) light for Profile Rear (Red)                        
                                if(getCustomizedSetting(Profiles[Profile_Rear]) == Profile_ON) {
                                    LL_Brightness_set(E_LL_PWM_FRONT_RED, 100); LL_LED_ON(E_LL_PWM_FRONT_RED);
                                }            
                            } break;
                            default: break; // should not happen
                        }
                    }
                    #endif
                    //
                    #if 0 // braking animation acc to Flashing Pattern (JIRA: https://lumoshelmet.atlassian.net/browse/LF-55?atlOrigin=eyJpIjoiZmY5ZWIzYTk5NTE3NDVhZGJlZDZmMWU0NjVkYzU5NmQiLCJwIjoiaiJ9)
                    {
                        // Meixuan Oh July 27, 2022 at 5:15 PM
                        //  When ring light is solid, use Mode 2’s brake light pattern.
                        //  When ring light is flashing, use Mode 1’s brake light pattern.
                        unsigned long flashing_pattern = LL_Para__get_flashing_pattern(gtPara.eModeOfWarningLight, E_LL_PWM_FRONT_RED);
                        if(0x00FFFFFF == flashing_pattern) { // if solid
                            // lights for braking (dual LEDs, also yellow)
                            LL_Brightness_set(E_LL_PWM_RED1, 100); LL_LED_Flashing(E_LL_PWM_RED1, LL_LED_BACK_FAST_FLASH_ON, LL_LED_BACK_FAST_FLASH_OFF);
                            LL_Brightness_set(E_LL_PWM_RED2, 100); LL_LED_Flashing(E_LL_PWM_RED2, LL_LED_BACK_FAST_FLASH_ON, LL_LED_BACK_FAST_FLASH_OFF);
                            LL_LED_OFF(E_LL_PWM_FRONT_YELLOW);
                            //
                            // other lights
                            // 1) light for Profile L/R (Blue)
                            if( (getCustomizedSetting(Profiles[Profile_L]) == Profile_ON)
                            ||  (getCustomizedSetting(Profiles[Profile_R]) == Profile_ON) ) {
                                LL_LED_OFF(E_LL_LED_PCB_B);
                            }
                            // 2) light for Profile Front (White)
                            if(getCustomizedSetting(Profiles[Profile_Front]) == Profile_ON) {
                                LL_Brightness_set(E_LL_PWM_FRONT_WHITE, 100); LL_LED_Flashing(E_LL_PWM_FRONT_WHITE, LL_LED_BACK_FAST_FLASH_ON, LL_LED_BACK_FAST_FLASH_OFF);
                            }
                            // 3) light for Profile Rear (Red)                        
                            if(getCustomizedSetting(Profiles[Profile_Rear]) == Profile_ON) {
                                LL_Brightness_set(E_LL_PWM_FRONT_RED, 100); LL_LED_Flashing(E_LL_PWM_FRONT_RED, LL_LED_BACK_FAST_FLASH_ON, LL_LED_BACK_FAST_FLASH_OFF);
                            }                                        
                        } else { // else, flashing
                            //
                            // lights for braking (dual LEDs, also yellow)
                            LL_Brightness_set(E_LL_PWM_RED1, 100); LL_LED_Flashing(E_LL_PWM_RED1, LL_LED_BACK_FAST_FLASH_ON, LL_LED_BACK_FAST_FLASH_OFF);
                            LL_Brightness_set(E_LL_PWM_RED2, 100); LL_LED_Flashing(E_LL_PWM_RED2, LL_LED_BACK_FAST_FLASH_ON, LL_LED_BACK_FAST_FLASH_OFF);
                            LL_LED_OFF(E_LL_PWM_FRONT_YELLOW);
                            //
                            // other lights
                            // 1) light for Profile L/R (Blue)
                            if( (getCustomizedSetting(Profiles[Profile_L]) == Profile_ON)
                            ||  (getCustomizedSetting(Profiles[Profile_R]) == Profile_ON) ) {
                                LL_LED_OFF(E_LL_LED_PCB_B);
                            }
                            // 2) light for Profile Front (White)
                            if(getCustomizedSetting(Profiles[Profile_Front]) == Profile_ON) {
                                LL_Brightness_set(E_LL_PWM_FRONT_WHITE, 100); LL_LED_ON(E_LL_PWM_FRONT_WHITE);
                            }
                            // 3) light for Profile Rear (Red)                        
                            if(getCustomizedSetting(Profiles[Profile_Rear]) == Profile_ON) {
                                LL_Brightness_set(E_LL_PWM_FRONT_RED, 100); LL_LED_ON(E_LL_PWM_FRONT_RED);
                            }                                        
                        }
                    }
                    #endif
                    //
                    #if 1 // braking animation Only One (JIRA: https://lumoshelmet.atlassian.net/browse/LF-55?focusedCommentId=10251)
                    {
                        // Meixuan Oh: New brake pattern (Only one): Solid red ring + dual led light at 100% PWM at 2s
                        LL_Brightness_set(E_LL_PWM_RED1, 100); LL_LED_ON(E_LL_PWM_RED1);
                        LL_Brightness_set(E_LL_PWM_RED2, 100); LL_LED_ON(E_LL_PWM_RED2);
                        LL_Brightness_set(E_LL_PWM_FRONT_RED, 100); LL_LED_ON(E_LL_PWM_FRONT_RED);
                    }
                    #endif
                }
            } else { // else, braking feature is disabled
                // nothing but resume Front/Rear
                prev_mode_of_Front = 0;
                prev_mode_of_Rear  = 0;
            }
        } else { // else, no braking (and no turning)
            //
            // turn off all the braking lights
            LL_LED_OFF(E_LL_PWM_RED1);
            LL_LED_OFF(E_LL_PWM_RED2);
            LL_LED_OFF(E_LL_PWM_FRONT_WHITE);
            LL_LED_OFF(E_LL_PWM_FRONT_RED);
            LL_LED_OFF(E_LL_PWM_FRONT_YELLOW);
            //
            { // resume Front/Rear
                prev_mode_of_Front = 0;
                prev_mode_of_Rear  = 0;
            }            
        }
    }
}    



val_timestamp timestampReportBatteryToApp;



// Identify
val_0to255      identify_step;
val_timestamp   identify_timestamp;
void LL_Identify(void) {
    switch(identify_step) {
        case 0: {
            // OFF
        } break;
        case 1: {
            //
            #if 0 // depend on profile
            {
                LL_LED_OFF(E_LL_PWM_FRONT_WHITE);
                if(Profile_ON == getCustomizedSetting(Profiles[Profile_Front])) { LL_LED_Breathing(E_LL_PWM_FRONT_WHITE); }
                //
                LL_LED_OFF(E_LL_PWM_FRONT_RED);
                if(Profile_ON == getCustomizedSetting(Profiles[Profile_Rear ])) { LL_LED_Breathing(E_LL_PWM_FRONT_RED); }
                //
                LL_LED_OFF(E_LL_PWM_FRONT_YELLOW);
                LL_LED_OFF(E_LL_LED_PCB_B);
                if(Profile_ON == getCustomizedSetting(Profiles[Profile_L ])) { gtPara.customer_flashing_timeslot_states[gtPara.eModeOfWarningLight][E_LL_PWM_FRONT_YELLOW] = LL_LED_FLASHING_PATTERN__Indicator_Profile_L; LL_LED_FlashingByCustomer(E_LL_PWM_FRONT_YELLOW); } //{ LL_LED_SpinL(E_LL_PWM_FRONT_YELLOW); }
                if(Profile_ON == getCustomizedSetting(Profiles[Profile_R ])) { gtPara.customer_flashing_timeslot_states[gtPara.eModeOfWarningLight][E_LL_PWM_FRONT_YELLOW] = LL_LED_FLASHING_PATTERN__Indicator_Profile_R; LL_LED_FlashingByCustomer(E_LL_PWM_FRONT_YELLOW); } //{ LL_LED_SpinR(E_LL_PWM_FRONT_YELLOW); }      
            }
            #endif
            #if 1 // Flashing yellow only, acc to: https://lumoshelmet.atlassian.net/browse/LF-86?focusedCommentId=10327
            {
                LL_LED_OFF(E_LL_PWM_FRONT_WHITE);
                LL_LED_OFF(E_LL_PWM_FRONT_RED);
                LL_LED_OFF(E_LL_PWM_RED1);
                LL_LED_OFF(E_LL_PWM_RED2);
                LL_LED_OFF(E_LL_PWM_FRONT_YELLOW);
                LL_LED_OFF(E_LL_LED_PCB_B);
								LL_LED_OFF(E_LL_LED_PCB_R);
								LL_LED_OFF(E_LL_LED_PCB_G);
                //
                LL_LED_Flashing(E_LL_PWM_FRONT_YELLOW, 150, 150);
            }
            #endif
            //
            identify_timestamp = CLOCK_ms;
            identify_step++;
        } break;
        case 2: {
            if(LL_Timer_Elapsed_ms(identify_timestamp) > 2000) { // if timeout 2s
                //
                LL_LEDs_OFF();//LL_LED_OFF(E_LL_LED_PCB_B); 
//                for(int cs = 1; cs <= 4; cs++) {
//                    LL_LED_Panel__setBuffer(0, cs, RGB_swR,   0); // turn OFF
//                    LL_LED_Panel__setBuffer(0, cs, RGB_swG,   0); // turn OFF
//                    LL_LED_Panel__setBuffer(0, cs, RGB_swB,   0); // turn OFF
//                }; LL_LED_Panel__refresh(); 
                //
                mode               = gtPara.eModeOfWarningLight;//1;
                prev_mode_of_Front = 0;
                prev_mode_of_Rear  = 0;                                    
                //
                identify_step = 0;
            }
        } break;
    }
}



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void LL_FetchButtonMessage(void) {
    tKeyEvt.N = 0xFFFFFFFF; 
    LL_Key_EvtFetch(&tKeyEvt);
}



// a common reading of button event
//LL_FetchButtonMessage;

// a common module for all the "Long Press":
//
val_0to255      isPowerButtonPressed = 0;
val_timestamp   timestampRecentPressOfPowerButton;
//
void LL_ButtonLongPress(void) {
    if(LL_ButtonPressed(POWER_BUTTON)) { // if power button pressed
        isPowerButtonPressed = 1; timestampRecentPressOfPowerButton = CLOCK_ms; // record the press time for "long press" event
    //    LL_LED_ON(E_LL_LED_PCB_B); // indicator for Toggle state of Touch Button (also Physical Button since they share the same pin)
    }
    if(LL_ButtonReleased(POWER_BUTTON)) { // if power button released
        isPowerButtonPressed = 0; // cancel the press flag which for "long press" event
    //    LL_LED_OFF(E_LL_LED_PCB_B); // indicator for Toggle state of Touch Button (also Physical Button since they share the same pin)
    }
}

// a common module for all the "Double Click":
//
val_0to255 ClickHappened = 0; // 1: Single Click.   2: Double Click.    3: 3 Click (for switching Profile)
//
val_0to255      countRelease = 0;
val_timestamp   timestampPreviousRelease;
void LL_ButtonMultipleClick(void) {
    if(LL_ButtonReleased(POWER_BUTTON)) { // if power button released
        #if 0
        countRelease++; if(1==countRelease) {
            timestampPreviousRelease = CLOCK_ms; // just record the time for the checking of possible coming Double Click
        } else if(2==countRelease) {
            if(LL_Timer_Elapsed_ms(timestampPreviousRelease) < 500) { // if 2nd release happened in 0.5s
                ClickHappened = 2;
                countRelease = 0;
            } else { // else, the 2nd release happened more than 0.5s after
                // reset it to be the 1st release
                countRelease = 1;
                timestampPreviousRelease = CLOCK_ms; // just record the time for the checking of possible coming Double Click
            }
        } else { // exception
            countRelease = 0;
        }
        #endif
        countRelease++; timestampPreviousRelease = CLOCK_ms;
    }
    //
    #if 0
    if(1==countRelease) {
        if(LL_Timer_Elapsed_ms(timestampPreviousRelease) < 500) { // if still in the 0.5s after the 1st release
            // continue wait for the possible 2nd release (Double Click)
        } else { // else, timeout, which means it's a Single Click
            countRelease = 0;
            ClickHappened = 1;        
        }
    }
    #endif
    if(0!=countRelease) {
        if(LL_Timer_Elapsed_ms(timestampPreviousRelease) < 500) { // if still in the 0.5s after the 1st release
            // continue wait for the possible next release (n Click)
        } else { // else, timeout, which means it's a n-1 Click
            ClickHappened = countRelease; countRelease = 0;
        }
    }
}



void LL_ChangeTo_state_PAIRING(void) { 
    LL_LED_OFF(E_LL_PWM_FRONT_WHITE);
    if(Profile_ON == getCustomizedSetting(Profiles[Profile_Front])) { LL_LED_Breathing(E_LL_PWM_FRONT_WHITE); }
    LL_LED_OFF(E_LL_PWM_FRONT_RED);
    if(Profile_ON == getCustomizedSetting(Profiles[Profile_Rear ])) { LL_LED_Breathing(E_LL_PWM_FRONT_RED); }
    LL_LED_OFF(E_LL_PWM_FRONT_YELLOW);
    LL_LED_OFF(E_LL_LED_PCB_B);
		LL_LED_OFF(E_LL_LED_PCB_G);
		LL_LED_OFF(E_LL_LED_PCB_R);
		                                                                                                                                                                                                               
    if(Profile_ON == getCustomizedSetting(Profiles[Profile_L ])) { gtPara.customer_flashing_timeslot_states[gtPara.eModeOfWarningLight][E_LL_PWM_FRONT_YELLOW] = LL_LED_FLASHING_PATTERN__Indicator_Profile_L;
																																		LL_LED_FlashingByCustomer(E_LL_PWM_FRONT_YELLOW);
																																	} //{ LL_LED_SpinL(E_LL_PWM_FRONT_YELLOW); }
		if(Profile_ON == getCustomizedSetting(Profiles[Profile_R ])) { gtPara.customer_flashing_timeslot_states[gtPara.eModeOfWarningLight][E_LL_PWM_FRONT_YELLOW] = LL_LED_FLASHING_PATTERN__Indicator_Profile_R; 
																																		LL_LED_FlashingByCustomer(E_LL_PWM_FRONT_YELLOW); 
																																	} //{ LL_LED_SpinR(E_LL_PWM_FRONT_YELLOW); }
																																
		if(Profile_ON != getCustomizedSetting(Profiles[Profile_Rear ]) && Profile_ON != getCustomizedSetting(Profiles[Profile_Front])) { LL_LED_Breathing(E_LL_PWM_FRONT_YELLOW); }
    //
    // wireless BLE
    LL_BLE_SetAdManu(LL_BLE_ADV_PAIRING_FLAG); battery_level_update(); ble_advertising_start(BLE_ADV_MODE_FAST); 
    // wireless 2.4GHz
    gtSysState.ulNoConnectionSinceSysOn = 1; ESB_address_type = 1; timeslot_sd_start();
    //
    mode               = 0;
    prev_mode_of_Front = 0;
    prev_mode_of_Rear  = 0;      
    //    
    state_ChangeTo(state_PAIRING);    
}
void LL_ChangeTo_state_ON(void) { // copy from LL_Helmet_ChangeStateTo_ON
    // lights:
    LL_LEDs_OFF(); //LL_LED_OFF(E_LL_LED_PCB_B);
    //
    // wireless BLE
    LL_BLE_SetAdManu(0); battery_level_update(); ble_advertising_start(BLE_ADV_MODE_FAST); 
    // wireless 2.4GHz
    gtSysState.ulNoConnectionSinceSysOn = 1; ESB_address_type = 0; timeslot_sd_start();
    //
    mode               = gtPara.eModeOfWarningLight;//1;
    prev_mode_of_Front = 0;
    prev_mode_of_Rear  = 0;                    
    //
    geBroadcastState = E_BROADCAST_STATE__NEED_PTX_OnlyClock; // sync
    //
    state_ChangeTo(state_ON);    
}



void LL_state_JUST_WAKE_UP(void) {
            state_ChangeTo(state_WAIT_FOR_THE_POSSIBLE_BUTTON_EVENT);
            if(getCustomizedSetting(Profiles[Profile_L]) == Profile_ON) {
                LL_PWM_DutySet(E_LL_PWM_FRONT_YELLOW, 25);
                LL_PWM_DutySet(E_LL_LED_PCB_B, 25);
            }
            if(getCustomizedSetting(Profiles[Profile_R]) == Profile_ON) {
                LL_PWM_DutySet(E_LL_PWM_FRONT_YELLOW, 25);
                LL_PWM_DutySet(E_LL_LED_PCB_B, 25);
            }        
            if(getCustomizedSetting(Profiles[Profile_Rear]) == Profile_ON) {
                LL_PWM_DutySet(E_LL_PWM_FRONT_RED, 25);            
            }
}
void LL_state_WAIT_FOR_THE_POSSIBLE_BUTTON_EVENT(void) {
            if(LL_Timer_Elapsed_ms(timestamp_StateMachine) > 100) { // if already 100ms after Wake Up
                state_ChangeTo(state_SLEEP);  // still no button event 100ms after wake up, then go to sleep
            }        
            if(LL_ButtonPressed(POWER_BUTTON)) { // if power button pressed
                state_ChangeTo(state_WAIT_FOR_THE_POSSIBLE_LONG_PRESS_OF_POWER_ON); // go to next state
            }  
            if(1 == gtPara.enabledHallSensor) {
                if(LL_ButtonPressed(LL_KEY__HallSensor)) { // if Hall Sensor attached
                    state_ChangeTo(state_WAIT_FOR_THE_POSSIBLE_LONG_PRESS_OF_POWER_ON); // go to next state
                } 
            }            
}
void LL_state_WAIT_FOR_THE_POSSIBLE_LONG_PRESS_OF_POWER_ON(void) {
            if(LL_Timer_Elapsed_ms(timestamp_StateMachine) > (200-100)) { // if already 200ms long (not long actually) press
                fade_onoff_init(0, gtPara.brightness[gtPara.eModeOfWarningLight]);
                LL_BatteryIndicator__Start();
                state_ChangeTo(state_FADE_ON);
            }    
            if(LL_ButtonReleased(POWER_BUTTON)) { // if power button released
                state_ChangeTo(state_SLEEP);  // button not hold long enough, go to sleep
            }      
}
void LL_state_FADE_ON(void) {
//          if(LL_Timer_Elapsed_ms(timestamp_StateMachine) > 10) { timestamp_StateMachine = CLOCK_ms; // a 10ms loop timeout
                fade_onoff_loop(); if(fade_onoff_brightness_current == fade_onoff_brightness_target) {
                    mode               = gtPara.eModeOfWarningLight;//1;
                    prev_mode_of_Front = 0;
                    prev_mode_of_Rear  = 0;
                    state_ChangeTo(state_ON_1st_3S_FOR_POSSIBLE_LONG_PRESS_OF_PAIRING);
                    //
                    if(Profile_ON == getCustomizedSetting(Profiles[Profile_L ])) { 
                        {
                            LL_LED_OFF(E_LL_PWM_FRONT_WHITE); 
                            LL_LED_OFF(E_LL_PWM_FRONT_RED); 
                            LL_LED_OFF(E_LL_PWM_FRONT_YELLOW); 
                        }
                        //
                        // yellow flash for left and double yellow flash for right
                        #if 0 // 3 times
                            gtPara.customer_flashing_timeslot_states[gtPara.eModeOfWarningLight][E_LL_PWM_FRONT_YELLOW] = LL_LED_FLASHING_PATTERN__Indicator_Profile_L_whenPowerOn;
                            LL_LED_FlashingByCustomer_times(E_LL_PWM_FRONT_YELLOW, 1);
                        #endif
                        #if 1 // single time (the 1st and last "OFF" are needed to seperate the indicator from the other flashing pattern)
                            LL_LED_OFF( E_LL_PWM_FRONT_YELLOW ); nrf_delay_ms(200);
                            {
                                LL_LED_ON(  E_LL_PWM_FRONT_YELLOW ); nrf_delay_ms(83); // 83ms: a half bar
                                LL_LED_OFF( E_LL_PWM_FRONT_YELLOW ); nrf_delay_ms(83); // 83ms: a half bar
                            }
                            LL_LED_OFF( E_LL_PWM_FRONT_YELLOW ); nrf_delay_ms(500);
                        #endif
                    }
                    if(Profile_ON == getCustomizedSetting(Profiles[Profile_R ])) { 
                        {
                            LL_LED_OFF(E_LL_PWM_FRONT_WHITE); 
                            LL_LED_OFF(E_LL_PWM_FRONT_RED);
                            LL_LED_OFF(E_LL_PWM_FRONT_YELLOW); 
                        }
                        //
                        // yellow flash for left and double yellow flash for right
                        #if 0 // 3 times
                            gtPara.customer_flashing_timeslot_states[gtPara.eModeOfWarningLight][E_LL_PWM_FRONT_YELLOW] = LL_LED_FLASHING_PATTERN__Indicator_Profile_R_whenPowerOn; 
                            LL_LED_FlashingByCustomer_times(E_LL_PWM_FRONT_YELLOW, 1); 
                        #endif
                        #if 1 // single time (the 1st and last "OFF" are needed to seperate the indicator from the other flashing pattern)
                            LL_LED_OFF( E_LL_PWM_FRONT_YELLOW ); nrf_delay_ms(200);
                            {
                                LL_LED_ON(  E_LL_PWM_FRONT_YELLOW ); nrf_delay_ms(83); // 83ms: a half bar
                                LL_LED_OFF( E_LL_PWM_FRONT_YELLOW ); nrf_delay_ms(83); // 83ms: a half bar
                                LL_LED_ON(  E_LL_PWM_FRONT_YELLOW ); nrf_delay_ms(83); // 83ms: a half bar
                                LL_LED_OFF( E_LL_PWM_FRONT_YELLOW ); nrf_delay_ms(83); // 83ms: a half bar
                            }
                            LL_LED_OFF( E_LL_PWM_FRONT_YELLOW ); nrf_delay_ms(500);
                        #endif
                    }
                }
//          }    
}
void LL_state_ON_1st_3S_FOR_POSSIBLE_LONG_PRESS_OF_PAIRING(void) {
            if(isPowerButtonPressed) { // if powe button pressed (maybe a long press for pairing)
                if(LL_Timer_Elapsed_ms(timestampRecentPressOfPowerButton) > 2*1000) { // if 2s timeout
                    isPowerButtonPressed = 0; LL_Key_IgnoreNextRelease(POWER_BUTTON); LL_ChangeTo_state_PAIRING();
                }
            } else { // else, power button released
//              if(LL_Timer_Elapsed_ms(timestamp_StateMachine) > 2*1000) { // if 2s timeout (for yellow light indicator of Profile L/R)
                if(0 == gtLED[E_LL_PWM_FRONT_YELLOW].ulON) { // if yellow indicator done
                    geBroadcastState = E_BROADCAST_STATE__NEED_PTX_OnlyClock; // sync
                    LL_ChangeTo_state_ON();    
                }                    
            }
//            if(LL_Timer_Elapsed_ms(timestamp_StateMachine) > 3*1000) { // if 3s timeout
//                geBroadcastState = E_BROADCAST_STATE__NEED_PTX_OnlyClock; // sync
//                isPowerButtonPressed = 0; LL_ChangeTo_state_ON();
//            }
//            if(LL_ButtonReleased(POWER_BUTTON)) { // if power button released
//                geBroadcastState = E_BROADCAST_STATE__NEED_PTX_OnlyClock; // sync
//                LL_ChangeTo_state_ON();
//            }
}
void LL_state_ON(void) {
            {
    //            if(LL_ButtonReleased(LL_KEY_NUM_ONOFF)) { // if button event "released"
    //                modeSwitchToNext;
    //            }    
                if(ClickHappened) { 
                    if(1 == ClickHappened) {
                        modeSwitchToNext; //TxCurrentFlashModeToApp();
                        //
                        LL_Para__set_flashing_pattern_fromButtonSwitch(); // disable the "temporary pattern from sync" actually
                        //
                        gtPara.eModeOfWarningLight     = (E_ModeOfWarningLight)(mode-1); gulFlashStoreNeeded = 1;// sync the mode of LumOS to old code 
                        gtSysState.eModeOfWarningLight = (E_ModeOfWarningLight)(mode-1); // sync the mode of LumOS to old code
                        TxCurrentFlashModeToApp(); // should after the "eModeOfWarningLight" be updated
                    } else if(2 == ClickHappened) {
                        //if(1 == gtPara.publicNetworkEnabled) { // if public sync is enabled        
                            geBroadcastState = E_BROADCAST_STATE__NEED_PTX; // sync
                        //}                
    //                } else if(3 == ClickHappened) {
    //                    if(getCustomizedSetting(Profiles[Profile_Front]) == Profile_ON) { // Front Light implement 
    //                        setPara(Profiles[Profile_Front] , Profile_OFF);
    //                        setPara(Profiles[Profile_Rear ] , Profile_ON );
    //                    } else {
    //                        setPara(Profiles[Profile_Front] , Profile_ON );
    //                        setPara(Profiles[Profile_Rear ] , Profile_OFF);
    //                    }                        
                    }
                ClickHappened = 0; }
            }
            if(isPowerButtonPressed) { // if powe button pressed (maybe a long press for power off)
                if(LL_Timer_Elapsed_ms(timestampRecentPressOfPowerButton) > 2*1000) { // if 2s timeout
                    if(1 == getPara(syncPowerOff)) {
                        geBroadcastState = E_BROADCAST_STATE__NEED_PTX_PowerOffMessage; // sync "power off"
                    }
                    //
                    LL_LEDs_OFF();
                    fade_onoff_init(gtPara.brightness[gtPara.eModeOfWarningLight], 0); LL_BatteryIndicator__Start();
                    state_ChangeTo(state_FADE_OFF);
                }
            }
            if(1 == gtPara.enabledHallSensor) {
                if(LL_ButtonReleased(LL_KEY__HallSensor)) { // if Hall Sensor apart
                    geBroadcastState = E_BROADCAST_STATE__NEED_PTX_PowerOffMessage; // sync "power off"
                    //
                    LL_LEDs_OFF();
                    fade_onoff_init(gtPara.brightness[gtPara.eModeOfWarningLight], 0);
                    state_ChangeTo(state_FADE_OFF);
                }         
            }            
            if(received_2p4GHz_message) {
                handle_2p4GHz_message_from_remote;
                    #ifdef _LL_AUTO_TESTING
                        if(0 == sgtMsg.usVerDate) { // if 1st packet of new testing round
                            if(previous_packetID != sgtMsg.usVerDate) { // if new packet
                                // reset the counter
                                count_received_O = 0;
                                count_received_L = 0;
                                count_received_R = 0;
                                count_received_N = 0;
                                count_received_K = 0;
                            }
                        }
                    #endif                        
                    //val_0to255 turning_temp;
                    switch(sgtMsg.cStateTurn) {
                        case 'O' : 
                            turning = LL_TURNING_NO; 
                            #ifdef _LL_AUTO_TESTING
                                if(previous_packetID != sgtMsg.usVerDate) { // if new packet
                                    count_received_O++;
                                }
                            #endif                        
    //                        { // resume Front/Rear
    //                            prev_mode_of_Front = 0;
    //                            prev_mode_of_Rear  = 0;
    //                        }
                        break;
                        case 'L' : 
                            turning = LL_TURNING_L; 
                            #ifdef _LL_AUTO_TESTING
                                if(previous_packetID != sgtMsg.usVerDate) { // if new packet
                                    count_received_L++;
                                }
                            #endif                        
                        break;
                        case 'R' : 
                            turning = LL_TURNING_R; 
                            #ifdef _LL_AUTO_TESTING
                                if(previous_packetID != sgtMsg.usVerDate) { // if new packet
                                    count_received_R++;
                                }
                            #endif    
												break;
												case 'E' :
														turning = LL_EMERGENCY_FLASH;
                        break;
                    }
                    //val_0to255 braking_temp;
                    switch(sgtMsg.cStateBrake) {
                        case 'N' : 
                            braking = LL_BRAKING_NO; 
                            #ifdef _LL_AUTO_TESTING
                                if(previous_packetID != sgtMsg.usVerDate) { // if new packet
                                    count_received_N++;
                                }
                            #endif                        
                        break;
                        case 'K' : 
                            braking = LL_BRAKING_YES; 
                            #ifdef _LL_AUTO_TESTING
                                if(previous_packetID != sgtMsg.usVerDate) { // if new packet
                                    count_received_K++;
                                }
                            #endif                        
                        break;
                    }
                    #ifdef _LL_AUTO_TESTING
                        if(previous_packetID != sgtMsg.usVerDate) { previous_packetID = sgtMsg.usVerDate; } // if new packet
                    #endif                        
//                    if((braking != braking_temp) || (turning != turning_temp)) { braking = braking_temp; turning = turning_temp; // if any change
                        message_handle_of_turning_and_braking();
//                    }
            received_2p4GHz_message = 0; }
            if(received_ble_message) { // if received BLE message
                //
                // handle the message (legacy, not include new ones for Bike Light)
                handle_ble_normalMode_message_from_app;
                //
                // handle the message (new ones for Bike Light)
                {
                    if(2 == ble_message_length) {
                        signed char turning_state = ble_message[0];
                        signed char braking_state = ble_message[1];
                        switch(turning_state) {
                            case 'O' : 
                                turning = LL_TURNING_NO; 
//                                { // resume Front/Rear
//                                    prev_mode_of_Front = 0;
//                                    prev_mode_of_Rear  = 0;
//                                }
                            break;
                            case 'L' : 
                                turning = LL_TURNING_L; 
                            break;
                            case 'R' : 
                                turning = LL_TURNING_R; 
                            break;
														case 'E' :
																turning = LL_EMERGENCY_FLASH;
														break;
                        }
                        switch(braking_state) {
                            case 'N' : 
                                braking = LL_BRAKING_NO; 
                            break;
                            case 'K' : 
                                braking = LL_BRAKING_YES; 
                            break;
                        }                
                        message_handle_of_turning_and_braking();                        
                    }
                    if(3 == ble_message_length) {
                        if(0 == memcmp("AT?", ble_message, 3)) { // if message  "AT?" (Auto Testing)
                            sprintf(string, "S num: %d\0", gtPara.ssKxyz[0]); ble_nus_string_send(&m_nus, (uint8_t *)string, strlen(string));
                            sprintf(string, "S int: %d\0", gtPara.ssKxyz[1]); ble_nus_string_send(&m_nus, (uint8_t *)string, strlen(string));
                            sprintf(string, "R num: %d\0", gtPara.ssKxyz[2]); ble_nus_string_send(&m_nus, (uint8_t *)string, strlen(string));
                            sprintf(string, "R int: %d\0", gtPara.ssThreshhold); ble_nus_string_send(&m_nus, (uint8_t *)string, strlen(string));
                        }
                    }
                    if(5 == ble_message_length) {
                        if (0 == memcmp("sync0", ble_message, 5)) { // if message is "sync0"
                            //if(1 == gtPara.publicNetworkEnabled) { // if public sync is enabled        
                                geBroadcastState = E_BROADCAST_STATE__NEED_PTX; // sync
                            //}                                            
                        }
                    }
                    if(ble_message_length == 8) {
                        if(0 == memcmp("Identify", ble_message, 8)) { // if message is "Identify"
                            identify_step = 1;
                        } else if(0 == memcmp("POWEROFF", ble_message, 8)) { // if message is "POWEROFF"
                            { // Power Off: copied from the one of "Long Press Power Off"
                                if(1 == getPara(syncPowerOff)) {
                                    geBroadcastState = E_BROADCAST_STATE__NEED_PTX_PowerOffMessage; // sync "power off"
                                }
                                //
                                LL_LEDs_OFF();
                                fade_onoff_init(gtPara.brightness[gtPara.eModeOfWarningLight], 0);  LL_BatteryIndicator__Start();
                                state_ChangeTo(state_FADE_OFF);         
                            }                                
                        } else if(0 == memcmp("AT", ble_message, 2)) { // if message has prefix "AT" (Auto Testing)
                            #ifdef _LL_AUTO_TESTING
                                //
                                // parse
                                unsigned char type  = ble_message[2] - '0';
                                unsigned long value = ((unsigned long)(ble_message[3] - '0')) * 10000
                                                    + ((unsigned long)(ble_message[4] - '0')) *  1000
                                                    + ((unsigned long)(ble_message[5] - '0')) *   100
                                                    + ((unsigned long)(ble_message[6] - '0')) *    10
                                                    + ((unsigned long)(ble_message[7] - '0')) *     1;
                                //
                                // handle
                                if(value > 32767) { // if more than a "signed short"
                                    sprintf(string, "need 0~32767\0");
                                } else { // else, the value is valid
                                    switch(type) {
                                        case 0: { // signal number
                                            gtPara.ssKxyz[0] = value; gulFlashStoreNeeded = 1;
                                            sprintf(string, "S num: %d\0", value);
                                        }; break;
                                        case 1: { // signal duration
                                            gtPara.ssKxyz[1] = value; gulFlashStoreNeeded = 1;
                                            sprintf(string, "S int: %d s\0", value);
                                        }; break;
                                        case 2: { // retransmission times
                                            gtPara.ssKxyz[2] = value; gulFlashStoreNeeded = 1;
                                            sprintf(string, "R num: %d\0", value);
                                        }; break;
                                        case 3: { // retransmission interval
                                            unsigned long signal_duration_required = gtPara.ssKxyz[1] * 1000;  // unit: ms
                                            unsigned long signal_duration_will_be  = gtPara.ssKxyz[2] * value; // unit: ms
                                            if(signal_duration_will_be > signal_duration_required) { // if use setting conflict
                                                sprintf(string, "conflict\0");
                                            } else { // else, user setting ok
                                                gtPara.ssThreshhold = value; gulFlashStoreNeeded = 1;
                                                sprintf(string, "R int: %d ms\0", value);
                                            }
                                        }; break;
                                        default: {
                                            sprintf(string, "unknown cmd\0");
                                        }; break;
                                    }
                                }
                                //
                                // response
                                ble_nus_string_send(&m_nus, (uint8_t *)string, strlen(string));                                
                            #endif
                        }
                    }
                    if(ble_message_length == 9) {
                        if(0 == memcmp("POWEROFF", ble_message, 8)) { char command = ble_message[8]; // turn ON/OFF sync POWER off
                            if('1' == command) { // if command "ON"
                                setPara(syncPowerOff, 1); // 1: enabled
                                gulFlashStoreNeeded = 1;
                            } else if('0' == command) { // else if command "OFF"
                                setPara(syncPowerOff, 0); // 0: disabled
                                gulFlashStoreNeeded = 1;
                            } else if('?' == command) { // else if command "read"
                                if(1 == getPara(syncPowerOff)) {
                                    sprintf(string, "POWEROFF1\0");
                                } else {
                                    sprintf(string, "POWEROFF0\0");
                                }
                                ble_nus_string_send(&m_nus, (uint8_t *)string, strlen(string));
                            }
                        }                        
                    }
                    if( (ble_message_length == 10) 
                    &&  (0 == memcmp("PROFILE ", ble_message, 8)) ) { // if message is 10 bytes AND has prefix "PROFILE ", may be "PROFILE nn" while "nn" is command
                        #define DOUBLE_QUESTION (('?' - '0') * 10 + ('?' - '0'))
                        unsigned long nn = (ble_message[8] - '0') * 10 
                                         + (ble_message[9] - '0'); 
                        if(nn == DOUBLE_QUESTION) { // if ??
                            sprintf(string, "%02d: %s", getPara(profile_nn), profile_names[getPara(profile_nn)]);
                            ble_nus_string_send(&m_nus, (uint8_t *)string, strlen(string));                        
                        } else { // else, nn
                            if(nn < TOTAL_PROFILE_NUM) {
                                //
                                setPara(profile_nn, nn);
                                setPara(Profiles[Profile_Front], onoff_Front[ nn ]);
                                setPara(Profiles[Profile_Rear ], onoff_Rear[  nn ]);
                                setPara(Profiles[Profile_L    ], onoff_L[     nn ]);
                                setPara(Profiles[Profile_R    ], onoff_R[     nn ]);
                                //
                                LL_LED_OFF(E_LL_PWM_FRONT_WHITE);
                                LL_LED_OFF(E_LL_PWM_FRONT_RED);
                                LL_LED_OFF(E_LL_PWM_RED1);
                                LL_LED_OFF(E_LL_PWM_RED2);
                                LL_LED_OFF(E_LL_PWM_FRONT_YELLOW);
                                LL_LED_OFF(E_LL_LED_PCB_B);
																LL_LED_OFF(E_LL_LED_PCB_R);
																LL_LED_OFF(E_LL_LED_PCB_G);
                                prev_mode_of_Front = 0;
                                prev_mode_of_Rear  = 0;                                            
                                //
                                sprintf(string, "Set %s", profile_names[getPara(profile_nn)]);
                                ble_nus_string_send(&m_nus, (uint8_t *)string, strlen(string));                                                        
                            } else { /* exception: unknown "nn" */ }
                        }
                    }
                    if( (ble_message_length == 11) 
                    &&  (0 == memcmp("DEL REMOTES", ble_message, 11)) ) { 
                        gtPara.tRemote.bits_isCheapRemote = 0;
                        for(int indexDevice = 0; indexDevice < DEVICE_NUM_OF_XXX; indexDevice++) {
                            memset(gtPara.tRemote.HardwareID[indexDevice].auc, 0xFF, LL_HARDWARE_ID_LEN);
                        }
                        sprintf(string, "Remotes deleted.\0");
                        ble_nus_string_send(&m_nus, (uint8_t *)string, strlen(string));                                                        
                    }
                }  
            received_ble_message = 0; }    
            if( ( (E_ModeOfWarningLight)(mode-1) != gtSysState.eModeOfWarningLight ) ) { // if changed by app command
                mode = gtSysState.eModeOfWarningLight + 1;
            }
            if(4000 <= LL_Timer_Elapsed_ms(timestampReportBatteryToApp)) { timestampReportBatteryToApp = gulTimerCnt1ms;
                //
                // battery level of helmet
                battery_level_update();
                //
                // battery level of remote
                if(    (1 == gulRemoteBatteryAutoUpdate) 
    //                && (SYS_PCB_TESTING_MODE != gtSysState.eOnOFF) 
    //                && (SYS_OFF != gtSysState.eOnOFF) 
    //                && (0 == gulCmdTestingMode)
    //                && (SYS_PRODUCTION_TESTING_MODE   != gtSysState.eOnOFF) 
                ) {
                                if(0xFFFFFFFF != gulBatteryOfRemote) { sprintf(string, "BL-R:%03u\0", gulBatteryOfRemote); }
                                else                                 { sprintf(string, "BL-R:NA\0");                    }
                                unsigned long ulLen = strlen(string); //if(strlen("BL-R:100") > ulLen) { ulLen = strlen("BL-R:100"); }
                                ble_nus_string_send(&m_nus, (uint8_t *)string, ulLen);
                }
                //
                #ifdef _LL_AUTO_TESTING
                    unsigned long ulLen;
                    sprintf(string, "got L: %d.\0", count_received_L); ulLen = strlen(string); ble_nus_string_send(&m_nus, (uint8_t *)string, ulLen);
                    sprintf(string, "got R: %d.\0", count_received_R); ulLen = strlen(string); ble_nus_string_send(&m_nus, (uint8_t *)string, ulLen);
                    sprintf(string, "got O: %d.\0", count_received_O); ulLen = strlen(string); ble_nus_string_send(&m_nus, (uint8_t *)string, ulLen);
                    sprintf(string, "got K: %d.\0", count_received_K); ulLen = strlen(string); ble_nus_string_send(&m_nus, (uint8_t *)string, ulLen);
                    sprintf(string, "got N: %d.\0", count_received_N); ulLen = strlen(string); ble_nus_string_send(&m_nus, (uint8_t *)string, ulLen);
                #endif
            }
            #if 1
            { // the profiles' routine
                // Profile Front
                if(0 != identify_step) { // if identifing
                    // skip when Pairing Mode or Identify
                } else {
										if(After_Pairing_Flag == 1){
											if(getCustomizedSetting(Profiles[Profile_Front]) == Profile_ON) { // Rear Light implement                        
												prev_mode_of_Front = mode;
											}else if(getCustomizedSetting(Profiles[Profile_Rear]) == Profile_ON) { // Rear Light implement                        
												prev_mode_of_Rear = mode;
											}
											After_Pairing_Flag = 0;
										}	
                    if(getCustomizedSetting(Profiles[Profile_Front]) == Profile_ON) { // Front Light implement
                        if(mode != prev_mode_of_Front) { prev_mode_of_Front = mode;
                    //        //
                    //        LL_Para__set_flashing_pattern_fromButtonSwitch(); // disable the "temporary pattern from sync" actually
                    //        //
                    //        gtPara.eModeOfWarningLight     = (E_ModeOfWarningLight)(mode-1); // sync the mode of LumOS to old code 
                    //        gtSysState.eModeOfWarningLight = (E_ModeOfWarningLight)(mode-1); // sync the mode of LumOS to old code
                            //
                            LL_PWM_DutySet(E_LL_PWM_FRONT_WHITE, gtPara.brightness[mode-1]);
                            if(mode == 1) {
                                LL_LED_FlashingByCustomer(E_LL_PWM_FRONT_WHITE);//LL_LED_ON(E_LL_PWM_FRONT_WHITE);
                            } else if(mode == 2) {
                                LL_LED_FlashingByCustomer(E_LL_PWM_FRONT_WHITE);//LL_LED_Flashing(E_LL_PWM_FRONT_WHITE, 2000*1/6, 2000*2/6);
                            } else if(mode == 3) {
                                LL_LED_FlashingByCustomer(E_LL_PWM_FRONT_WHITE);//LL_LED_Flashing(E_LL_PWM_FRONT_WHITE, 2000*1/6, 2000*1/6);
                            }    
                    //        //
                    //        if(1 == gtPara.publicNetworkEnabled) { // if public sync is enabled        
                    //            geBroadcastState = E_BROADCAST_STATE__NEED_PTX; // sync
                    //        }
                        }
                    } else { LL_LED_OFF(E_LL_PWM_FRONT_WHITE); }
                }

                // Profile Rear
                if(0 != identify_step) { // if identifing
                    // skip when Pairing Mode or Identify
                } else {
                    if(getCustomizedSetting(Profiles[Profile_Rear]) == Profile_ON) { // Rear Light implement
                        if(mode != prev_mode_of_Rear) { prev_mode_of_Rear = mode;
                    //        //
                    //        LL_Para__set_flashing_pattern_fromButtonSwitch(); // disable the "temporary pattern from sync" actually
                    //        //
                    //        gtPara.eModeOfWarningLight     = (E_ModeOfWarningLight)(mode-1); // sync the mode of LumOS to old code 
                    //        gtSysState.eModeOfWarningLight = (E_ModeOfWarningLight)(mode-1); // sync the mode of LumOS to old code
                            //
                            LL_PWM_DutySet(E_LL_PWM_FRONT_RED,  gtPara.brightness[mode-1]);
                            #if 0 // Dual Red %: Mode
                            {
                                LL_PWM_DutySet(E_LL_PWM_RED1, gtPara.brightness[mode-1]);
                                LL_PWM_DutySet(E_LL_PWM_RED2, gtPara.brightness[mode-1]);
                            }
                            #else // Dual Red %: 100%
                            {
                                LL_PWM_DutySet(E_LL_PWM_RED1, 100);
                                LL_PWM_DutySet(E_LL_PWM_RED2, 100);
                            }
                            #endif
                            #if 0 // the demo of Dual Red
                                if(mode == 1) {
                                    LL_LED_FlashingByCustomer(E_LL_PWM_FRONT_RED);//LL_LED_ON(E_LL_PWM_FRONT_RED);
                                    { // demo for COB red1&2
                                        LL_LED_OFF(E_LL_PWM_RED1); 
                                        LL_LED_OFF(E_LL_PWM_RED2);                         
                                    }
                                } else if(mode == 2) {
                                    LL_LED_FlashingByCustomer(E_LL_PWM_FRONT_RED);//LL_LED_Flashing(E_LL_PWM_FRONT_RED, 2000*1/6, 2000*2/6);
                                    { // demo for COB red1&2
                                        LL_LED_FlashingByCustomer(E_LL_PWM_RED1); 
                                        LL_LED_FlashingByCustomer(E_LL_PWM_RED2);                         
                                    }
                                } else if(mode == 3) {
                                    LL_LED_FlashingByCustomer(E_LL_PWM_FRONT_RED);//LL_LED_Flashing(E_LL_PWM_FRONT_RED, 2000*1/6, 2000*1/6);
                                    { // demo for COB red1&2
                                        LL_LED_FlashingByCustomer(E_LL_PWM_RED1); 
                                        LL_LED_FlashingByCustomer(E_LL_PWM_RED2);                         
                                    }
                                }    
                            #else
                                LL_LED_FlashingByCustomer(E_LL_PWM_FRONT_RED); 
                                LL_LED_FlashingByCustomer(E_LL_PWM_RED1); 
                                LL_LED_FlashingByCustomer(E_LL_PWM_RED2);                                                     
                            #endif
                    //        //
                    //        if(1 == gtPara.publicNetworkEnabled) { // if public sync is enabled        
                    //            geBroadcastState = E_BROADCAST_STATE__NEED_PTX; // sync
                    //        }
                        }
                        //
                    #if 0 // should not always working!   
                        if(braking == LL_BRAKING_YES) {
                            LL_LED_ON(E_LL_PWM_FRONT_RED);        
                        } else {
                            prev_mode_of_Rear = 0; //LL_LED_OFF(E_LL_PWM_FRONT_RED);
                        }
                    #endif    
    //                    val_timestamp last_timestamp_that_braking_is_off;
    //                    if(braking == LL_BRAKING_NO) {
    //                        last_timestamp_that_braking_is_off = CLOCK_ms;
    //                    } else { // else, turning
    //                        if(LL_Timer_Elapsed_ms(last_timestamp_that_braking_is_off) > 2*1000) { // if 2s timeout
    //                            braking = LL_BRAKING_NO;
    //                        }
    //                    }    
                    } else {
                        if(braking == LL_BRAKING_YES) { // if braking
                            // nothing: not turn off the COB red since it's used for braking animation
                        } else { // else, no braking
                            LL_LED_OFF(E_LL_PWM_FRONT_RED); 
                        }
                    }
                }

                // Profile L
                if(0 != identify_step) { // if identifing
                    // skip when Pairing Mode or Identify
                } else {
                    if(getCustomizedSetting(Profiles[Profile_L]) == Profile_ON) {
//                        if( (turning == LL_TURNING_NO) && (braking == LL_BRAKING_NO) ) { LL_Brightness_set(E_LL_LED_PCB_B, gtPara.brightness[gtPara.eModeOfWarningLight]); LL_LED_ON(E_LL_LED_PCB_B); }
                    }
                }

                // Profile R
                if(0 != identify_step) { // if identifing
                    // skip when Pairing Mode or Identify
                } else {
                    if(getCustomizedSetting(Profiles[Profile_R]) == Profile_ON) {
//                        if( (turning == LL_TURNING_NO) && (braking == LL_BRAKING_NO) ) { LL_Brightness_set(E_LL_LED_PCB_B, gtPara.brightness[gtPara.eModeOfWarningLight]); LL_LED_ON(E_LL_LED_PCB_B); }
                    }
                }
                
                // Profile L/R only
                if( (E_Profile_LeftOnly  == getCustomizedSetting(profile_nn)) 
                ||  (E_Profile_RightOnly == getCustomizedSetting(profile_nn)) ) { // if the App Profile is L/R Only
                    if( (turning == LL_TURNING_NO) && (braking == LL_BRAKING_NO) ) { // if no turning and braking
                        // turn on the orange light
                        LL_Brightness_set(E_LL_LED_PCB_R, 100); LL_LED_ON(E_LL_LED_PCB_R);
												LL_Brightness_set(E_LL_LED_PCB_G, 25); LL_LED_ON(E_LL_LED_PCB_G); 

                    } else { // else, turning or braking
                        // let turning or braking module to handle the blue light
                    }
                } else { // else, must be other App Profile that no need blue light
										if( (gtPara.customer_flashing_timeslot_states[mode-1][E_LL_PWM_FRONT_WHITE] == 0x0000000) && (getCustomizedSetting(Profiles[Profile_Front]) == Profile_ON) ){
												LL_Brightness_set(E_LL_LED_PCB_G, 50);
												LL_Brightness_set(E_LL_LED_PCB_R, 100);
												LL_Brightness_set(E_LL_LED_PCB_B, 100);
												LL_LED_ON(E_LL_LED_PCB_B);
												LL_LED_ON(E_LL_LED_PCB_G);
												LL_LED_ON(E_LL_LED_PCB_R);				
										} else if( (gtPara.customer_flashing_timeslot_states[mode-1][E_LL_PWM_FRONT_RED] == 0x000000) && (getCustomizedSetting(Profiles[Profile_Rear]) == Profile_ON) 
												&& (gtPara.customer_flashing_timeslot_states[mode-1][E_LL_PWM_RED1] == 0x000000) && (gtPara.customer_flashing_timeslot_states[mode-1][E_LL_PWM_RED2] == 0x000000)){
													LL_Brightness_set(E_LL_LED_PCB_R, 100);
													LL_LED_ON(E_LL_LED_PCB_R);	
										} else {
													LL_LED_OFF(E_LL_LED_PCB_B);
													LL_LED_OFF(E_LL_LED_PCB_G);
													LL_LED_OFF(E_LL_LED_PCB_R);			
										}		
                }
            }
            #else // Light Pattern of prototype for testing lab (Slack: https://lumoshelmet.slack.com/archives/C0296RXE12R/p1660106633450219)
            {
                //Jerrell Today at 12:43
                //im going to need Xiong’s help to make 1 firmware for a prototype, where the preset flash modes are:
                //  1. white light (100% brightness)
                //  2. red COB only (100% brightness, solid)
                //  3. red COB 40% brightness, dual LED on (all of them solid)
                //  4. yellow, 100% brightness, solid
                //  basically need all of them to be solid, and then the test lab can cycle through the different colors via a single button press. quite similar to the firmware that Xiong provided to Gavin earlier on to test battery life (i think)                
                
                #define PATTERN_SOLID_OFF   0x00000000                
                #define PATTERN_SOLID_ON    0x00FFFFFF                
                unsigned char brightness[ E_MODE_OF_WARNING_LIGHT__NUM ][ LL_PWM_CH_NUM ] = { // index by Mode and E_LL_PWM
                    //  PCB_B   FRONT_WHITE     RED1    RED2    FRONT_RED   FRONT_YELLOW    BATT_LVL
                    {     0,    100,              0,      0,      0,          0,              0        },   // mode 1
                    {     0,      0,              0,      0,    100,          0,              0        },   // mode 2
                    {     0,      0,            100,    100,     40,          0,              0        },   // mode 3
                    {     0,      0,              0,      0,      0,        100,              0        }    // mode 4
                };
                unsigned long pattern[    E_MODE_OF_WARNING_LIGHT__NUM ][ LL_PWM_CH_NUM ] = { // index by Mode and E_LL_PWM
                    //  PCB_B               FRONT_WHITE         RED1                RED2                FRONT_RED           FRONT_YELLOW        BATT_LVL
                    {   PATTERN_SOLID_OFF,  PATTERN_SOLID_ON,   PATTERN_SOLID_OFF,  PATTERN_SOLID_OFF,  PATTERN_SOLID_OFF,  PATTERN_SOLID_OFF,  PATTERN_SOLID_OFF }, // mode 1
                    {   PATTERN_SOLID_OFF,  PATTERN_SOLID_OFF,  PATTERN_SOLID_OFF,  PATTERN_SOLID_OFF,  PATTERN_SOLID_ON,   PATTERN_SOLID_OFF,  PATTERN_SOLID_OFF }, // mode 2
                    {   PATTERN_SOLID_OFF,  PATTERN_SOLID_OFF,  PATTERN_SOLID_ON,   PATTERN_SOLID_ON,   PATTERN_SOLID_ON,   PATTERN_SOLID_OFF,  PATTERN_SOLID_OFF }, // mode 3
                    {   PATTERN_SOLID_OFF,  PATTERN_SOLID_OFF,  PATTERN_SOLID_OFF,  PATTERN_SOLID_OFF,  PATTERN_SOLID_OFF,  PATTERN_SOLID_ON,   PATTERN_SOLID_OFF }  // mode 4
                };
                        
                if(mode_for_prototype != prev_mode_for_prototype) { prev_mode_for_prototype = mode_for_prototype;
                    for(int light = 0; light < LL_PWM_CH_NUM; light++) {
                        // set brightness
                        LL_PWM_DutySet(light, brightness[mode_for_prototype-1][light]);
                        // set pattern
                        gtPara.customer_flashing_timeslot_states[mode-1][light] = pattern[mode_for_prototype-1][light];
                        // start the Flashing Pattern
                        LL_LED_FlashingByCustomer(light);
                    }                    
                }
            }
            #endif
						
						//App send "Pairing-Y" To Enter Pairing Mode in normal mode
						extern uint8_t AppViaPairingMode;
						
						if(AppViaPairingMode == 1)
						{
							AppViaPairingMode = 0;
							
							//yellow light flash 1 time
							if(Profile_ON == getCustomizedSetting(Profiles[Profile_L ])) { 
										LL_LED_OFF(E_LL_PWM_FRONT_WHITE); 
										LL_LED_OFF(E_LL_PWM_FRONT_RED); 
										LL_LED_OFF(E_LL_PWM_FRONT_YELLOW); 

										LL_LED_OFF( E_LL_PWM_FRONT_YELLOW ); nrf_delay_ms(200);
										{
												LL_LED_ON(  E_LL_PWM_FRONT_YELLOW ); nrf_delay_ms(83); // 83ms: a half bar
												LL_LED_OFF( E_LL_PWM_FRONT_YELLOW ); nrf_delay_ms(83); // 83ms: a half bar
										}
										LL_LED_OFF( E_LL_PWM_FRONT_YELLOW ); nrf_delay_ms(500);
								}
							
								//yellow light flash 2 times
								if(Profile_ON == getCustomizedSetting(Profiles[Profile_R ])) { 
										LL_LED_OFF(E_LL_PWM_FRONT_WHITE); 
										LL_LED_OFF(E_LL_PWM_FRONT_RED);
										LL_LED_OFF(E_LL_PWM_FRONT_YELLOW); 

										LL_LED_OFF( E_LL_PWM_FRONT_YELLOW ); nrf_delay_ms(200);
										{
												LL_LED_ON(  E_LL_PWM_FRONT_YELLOW ); nrf_delay_ms(83); // 83ms: a half bar
												LL_LED_OFF( E_LL_PWM_FRONT_YELLOW ); nrf_delay_ms(83); // 83ms: a half bar
												LL_LED_ON(  E_LL_PWM_FRONT_YELLOW ); nrf_delay_ms(83); // 83ms: a half bar
												LL_LED_OFF( E_LL_PWM_FRONT_YELLOW ); nrf_delay_ms(83); // 83ms: a half bar
										}
										LL_LED_OFF( E_LL_PWM_FRONT_YELLOW ); nrf_delay_ms(500);

								}
								
								//via pairing mode
								LL_ChangeTo_state_PAIRING();
						}
}
void LL_state_PAIRING(void) {
            if(!(the_current_profile_support_braking()) || (0 == gtPara.ulBrakeFunction)) { 
                //LL_LED_OFF(E_LL_LED_PCB_B);
                LL_LED_OFF(E_LL_PWM_RED1);
                LL_LED_OFF(E_LL_PWM_RED2);
            } else {
                //LL_LED_ON(E_LL_LED_PCB_B);
                LL_Brightness_set(E_LL_PWM_RED1, 5); LL_LED_ON(E_LL_PWM_RED1);
                LL_Brightness_set(E_LL_PWM_RED2, 5); LL_LED_ON(E_LL_PWM_RED2);
            }
            //
            if(0 != ClickHappened) {
                if(1/*3*/ == ClickHappened) {
                    // Front       == Rear
                    // Front Left  == Rear Left
                    // Front Right == Rear Right
                    unsigned long new_nn; switch(getCustomizedSetting(profile_nn)) {
                        case E_Profile_Default:     new_nn = E_Profile_Rear         ; break;
                        case E_Profile_Front:       new_nn = E_Profile_Rear         ; break;
                        case E_Profile_FrontLeft:   new_nn = E_Profile_RearLeft     ; break;
                        case E_Profile_FrontRight:  new_nn = E_Profile_RearRight    ; break;
                        case E_Profile_Rear:        new_nn = E_Profile_Front        ; break;
                        case E_Profile_RearLeft:    new_nn = E_Profile_FrontLeft    ; break;
                        case E_Profile_RearRight:   new_nn = E_Profile_FrontRight   ; break;
                        case E_Profile_LeftOnly:    new_nn = E_Profile_LeftOnly     ; break; // no change
                        case E_Profile_RightOnly:   new_nn = E_Profile_RightOnly    ; break; // no change
                        default:                    new_nn = E_Profile_Default      ; break; // exception
                    }       
                    setPara(profile_nn, new_nn);
                    setPara(Profiles[Profile_Front], onoff_Front[ new_nn ]);
                    setPara(Profiles[Profile_Rear ], onoff_Rear[  new_nn ]);
                    setPara(Profiles[Profile_L    ], onoff_L[     new_nn ]);
                    setPara(Profiles[Profile_R    ], onoff_R[     new_nn ]);
                    //
                    #if 0 // testing code: a fixed "yellow light indicator" for Gavin to improve the brightness
                        LL_LED_OFF(E_LL_PWM_FRONT_WHITE);
                        LL_LED_OFF(E_LL_PWM_FRONT_RED);
                        gtPara.customer_flashing_timeslot_states[gtPara.eModeOfWarningLight][E_LL_PWM_FRONT_YELLOW] = 0x00AA0AA0;
                        LL_LED_FlashingByCustomer(E_LL_PWM_FRONT_YELLOW);
                    #else // normal
                        if(Profile_ON == getCustomizedSetting(Profiles[Profile_Front])) { 
                            LL_LED_Breathing(E_LL_PWM_FRONT_WHITE); 
                        } else {
                            LL_LED_OFF(E_LL_PWM_FRONT_WHITE);
                        }
                        if(Profile_ON == getCustomizedSetting(Profiles[Profile_Rear ])) { 
                            LL_LED_Breathing(E_LL_PWM_FRONT_RED); 
                        } else {
                            LL_LED_OFF(E_LL_PWM_FRONT_RED);
                        }
                        LL_LED_OFF(E_LL_PWM_FRONT_YELLOW);
                        LL_LED_OFF(E_LL_LED_PCB_R);
												LL_LED_OFF(E_LL_LED_PCB_G);
                        //if(Profile_ON == getCustomizedSetting(Profiles[Profile_L ])) { LL_LED_Breathing(E_LL_PWM_FRONT_YELLOW); } //{ LL_LED_SpinL(E_LL_PWM_FRONT_YELLOW); }
                        //if(Profile_ON == getCustomizedSetting(Profiles[Profile_R ])) { LL_LED_Breathing(E_LL_PWM_FRONT_YELLOW); } //{ LL_LED_SpinR(E_LL_PWM_FRONT_YELLOW); }
												//flashing
                        if(Profile_ON == getCustomizedSetting(Profiles[Profile_L ])) { gtPara.customer_flashing_timeslot_states[gtPara.eModeOfWarningLight][E_LL_PWM_FRONT_YELLOW] = LL_LED_FLASHING_PATTERN__Indicator_Profile_L; LL_LED_FlashingByCustomer(E_LL_PWM_FRONT_YELLOW); } //{ LL_LED_SpinL(E_LL_PWM_FRONT_YELLOW); }
                        if(Profile_ON == getCustomizedSetting(Profiles[Profile_R ])) { gtPara.customer_flashing_timeslot_states[gtPara.eModeOfWarningLight][E_LL_PWM_FRONT_YELLOW] = LL_LED_FLASHING_PATTERN__Indicator_Profile_R; LL_LED_FlashingByCustomer(E_LL_PWM_FRONT_YELLOW); } //{ LL_LED_SpinR(E_LL_PWM_FRONT_YELLOW); }
												if(Profile_ON != getCustomizedSetting(Profiles[Profile_Front ]) && Profile_ON != getCustomizedSetting(Profiles[Profile_Rear ])) { LL_LED_Breathing(E_LL_PWM_FRONT_YELLOW); } //{ LL_LED_SpinL(E_LL_PWM_FRONT_YELLOW); }
   
												#endif
                }
                if(5 == ClickHappened) {
                    if(the_current_profile_support_braking()) {
                        if(0 == gtPara.ulBrakeFunction) { 
                            gtPara.ulBrakeFunction = 1;
                        } else { 
                            gtPara.ulBrakeFunction = 0;
                        }
                        gulFlashStoreNeeded = 1; 
                    }
                }
            ClickHappened = 0; }
            if(received_2p4GHz_message) { 
                if(55 > gulRSSI) {
                    if(sgtMsg.cStateBrake != 'C') { // if not Remote Lite
                        handle_2p4GHz_pairing_message_from_remote; 
												After_Pairing_Flag = 1;
                        LL_ChangeTo_state_ON();
                    }
                }
            //received_2p4GHz_message = 0; 
						}
            //
            if(received_ble_message) { // if received BLE message
                //
                // handle the message (legacy, not include new ones for Bike Light)
                handle_ble_pairing_message_from_app;
                if(1 == needExitPairingMode) { // copy from LL_Helmet_ChangeStateTo_ON
                    LL_ChangeTo_state_ON();
                } else { /* no need exit, wait for the possible pairing of remote */ }
            received_ble_message = 0; }
            //
            // Long Press to power off
            if(isPowerButtonPressed) { // if powe button pressed (maybe a long press for power off)
                if(LL_Timer_Elapsed_ms(timestampRecentPressOfPowerButton) > 2*1000) { // if 2s timeout
                    LL_LEDs_OFF();
                    fade_onoff_init(gtPara.brightness[gtPara.eModeOfWarningLight], 0); LL_BatteryIndicator__Start();
                    state_ChangeTo(state_FADE_OFF);
                }
            }    
            //
            void LL__Production_Testing(void);
            LL__Production_Testing();
}
void LL_state_FADE_OFF(void) {
//  if(LL_Timer_Elapsed_ms(timestamp_StateMachine) > 10) { timestamp_StateMachine = CLOCK_ms; // if 10ms timeout
        fade_onoff_loop(); if(fade_onoff_brightness_current == fade_onoff_brightness_target) {
            state_ChangeTo(state_SLEEP);
        }
//  }            
}
void LL_state_SLEEP(void) {
    if(isPowerButtonPressed) {
        // wait for the release
    } else {
        SLEEP;
    }
}
void LL_States(void) {
    switch(state) {
        case state_JUST_WAKE_UP: {
            LL_state_JUST_WAKE_UP();
        break; }
        case state_WAIT_FOR_THE_POSSIBLE_BUTTON_EVENT: {
            LL_state_WAIT_FOR_THE_POSSIBLE_BUTTON_EVENT();
        break; }
        case state_WAIT_FOR_THE_POSSIBLE_LONG_PRESS_OF_POWER_ON: {
            LL_state_WAIT_FOR_THE_POSSIBLE_LONG_PRESS_OF_POWER_ON();
        break; }
        case state_FADE_ON: {
            LL_state_FADE_ON();
        break; }
        case state_ON_1st_3S_FOR_POSSIBLE_LONG_PRESS_OF_PAIRING: {
            LL_state_ON_1st_3S_FOR_POSSIBLE_LONG_PRESS_OF_PAIRING();
        break; }
        case state_ON: {
            LL_state_ON();
        break; }
        case state_PAIRING: {
            LL_state_PAIRING();
        break; }
        case state_FADE_OFF: {
            LL_state_FADE_OFF();
        break; }
        case state_SLEEP: {
            LL_state_SLEEP();
        break; }
        default: {
        break; }
    }
}



val_timestamp last_timestamp_that_turning_is_off;
void LL_TurningAutoOff(void) {
    if(turning == LL_TURNING_NO || turning == LL_EMERGENCY_FLASH) {
        last_timestamp_that_turning_is_off = CLOCK_ms;
    } else { // else, turning
        if(LL_Timer_Elapsed_ms(last_timestamp_that_turning_is_off) > 2*60*1000) { // if 2min timeout
            turning = LL_TURNING_NO;
            #if 0
                { // resume Front/Rear
                    prev_mode_of_Front = 0;
                    prev_mode_of_Rear  = 0;
                }
            #else
                message_handle_of_turning_and_braking();
            #endif
        }
    }
}



val_timestamp last_timestamp_that_braking_is_off;
void LL_BrakingAutoOff(void) {
    if((the_current_profile_support_braking()) && (1 == gtPara.ulBrakeFunction)) { // if braking feature is ON
        if(braking == LL_BRAKING_NO) {
            last_timestamp_that_braking_is_off = CLOCK_ms;
        } else { // else, braking
            if(LL_Timer_Elapsed_ms(last_timestamp_that_braking_is_off) > 2*1000) { // if 2s timeout
                braking = LL_BRAKING_NO;
                #if 0
                    LL_LED_OFF(E_LL_PWM_FRONT_YELLOW);
                    { // resume Front/Rear
                        prev_mode_of_Front = 0;
                        prev_mode_of_Rear  = 0;
                    }
                #else
                    message_handle_of_turning_and_braking();
                #endif
            }
        }
    }
}



// Step 1: run your State Mathine according to your timing or the button or wireless message
/******************************************************************************************

if(ButtonPressed(POWER_BUTTON)) {
    set_brightness( WRITE_LUGHT, 50); turn_on_LED( WRITE_LUGHT);
    set_brightness(   RED_LUGHT, 50); turn_on_LED(   RED_LUGHT);
}

if( (ButtonPressed(BUTTON_Ldr0 
OR  (ButtonPressed(BUTTON_R)) ) {
    auto_sleep_timer = 15;
}

if(receivedAppMessage()) {
}


Mode 

if( PMsFlag) ) {
    auto_sleep_timer = 15;
}

******************************************************************************************/

#if 0 // "switch-case" is hard for PMs to understand
switch(PMsFlag) {
    //
    case 0: { // wait for the button detecting and wireless message receiving
        if(LL_Timer_Elapsed_ms(time_record) > 100) { // if already 100ms after Wake Up
            SLEEP   // still no button event 100ms after wake up, then go to sleep
        } else { // else, still in the 100ms after Wake Up
            LL_FetchButtonMessage   // read the button 
            if(LL_ButtonPressed(LL_KEY_NUM_ONOFF)) { // if power button pressed
                time_record = CLOCK_ms; // record the current time, unit: ms
                LL_PWM_DutySet(LL_PIN__PWR_FRONT_LIGHT, 50); LL_LED_ON(LL_PIN__PWR_FRONT_LIGHT); // turn on the white light with 50% brightness
                LL_PWM_DutySet(E_LL_PWM_FRONT_WHITE, 50); LL_LED_ON(E_LL_PWM_FRONT_WHITE); // turn on the white light with 50% brightness
                PMsFlag = 1; // go to next state
            }
        }
    break; }
    //
    case 1: { 
//        LL_FetchButtonMessage   // read the button 
//        if(LL_ButtonReleased(LL_KEY_NUM_ONOFF)) {
//            PMsFlag = 2; // go to next state
//        }
        do {
            LL_LED_ON(  E_LL_PWM_FRONT_WHITE); LL_ExclusiveDelay_ms(250);
            LL_LED_OFF( E_LL_PWM_FRONT_WHITE); LL_ExclusiveDelay_ms(250);
        } while(1);
    break; }
    //
    case 2: { 
        LL_FetchButtonMessage   // read the button 
        if(LL_ButtonReleased(LL_KEY_NUM_ONOFF)) {
            mode++; // next mode
            if(mode > 3) {
                mode = 1; // cycle to Mode 1
            }
            // light on acc to mode
            if(mode == 1) {
                LL_PWM_DutySet(E_LL_PWM_FRONT_WHITE, 50); LL_LED_ON(E_LL_PWM_FRONT_WHITE); // turn on the white light with 50% brightness
                LL_LED_OFF(E_LL_PWM_FRONT_YELLOW); 
                LL_LED_OFF(E_LL_PWM_FRONT_RED); 
            } else if(mode == 2) {
                LL_LED_OFF(E_LL_PWM_FRONT_WHITE); 
                LL_PWM_DutySet(E_LL_PWM_FRONT_YELLOW, 100); LL_LED_ON(E_LL_PWM_FRONT_YELLOW); 
                LL_LED_OFF(E_LL_PWM_FRONT_RED); 
            } else if(mode == 3) {
                LL_LED_OFF(E_LL_PWM_FRONT_WHITE); 
                LL_LED_OFF(E_LL_PWM_FRONT_YELLOW); 
                LL_PWM_DutySet(E_LL_PWM_FRONT_RED, 100); LL_LED_ON(E_LL_PWM_FRONT_RED); 
            }
        }
    break; }
}
#endif
