| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555 |
- /************************************************************
- * @brief button_drive
- * @param RT_NULL
- * @return RT_NULL
- * @author jiejie
- * @github https://github.com/jiejieTop
- * @date 2018-xx-xx
- * @version v1.0.1
- * @note button.c
- ***********************************************************/
- #include "button.h"
- #ifdef HUALI_PKG_USING_BUTTON
- /*******************************************************************
- * Variable Declaration
- *******************************************************************/
- static struct button* Head_Button = RT_NULL;
- /*******************************************************************
- * Function Declaration
- *******************************************************************/
- static char *StrnCopy(char *dst, const char *src, rt_uint32_t n);
- static void Print_Btn_Info(Button_t* btn);
- static void Add_Button(Button_t* btn);
- /************************************************************
- * @brief Create a Button
- * @param name:button name
- * @param btn:button structure
- * @param read_btn_level:Button trigger level reading function,
- * Return the level of the rt_uint8_t type by yourself
- * @param btn_trigger_level:Button trigger level
- * @return RT_NULL
- * @author jiejie
- * @github https://github.com/jiejieTop
- * @date 2018-xx-xx
- * @version v1.0
- * @note RT_NULL
- ***********************************************************/
- void Button_Create(const char *name,
- Button_t *btn,
- rt_uint8_t(*read_btn_level)(void),
- rt_uint8_t btn_trigger_level)
- {
- if( btn == RT_NULL)
- {
- RT_DEBUG_LOG(RT_DEBUG_THREAD,("struct button is RT_NULL!"));
- }
-
- memset(btn, 0, sizeof(struct button)); //Clear structure information
-
- StrnCopy(btn->Name, name, BTN_NAME_MAX); //button name
-
-
- btn->Button_State = NONE_TRIGGER; //Button status
- btn->Button_Last_State = NONE_TRIGGER; //Button last status
- btn->Button_Trigger_Event = NONE_TRIGGER; //Button trigger event
- btn->Read_Button_Level = read_btn_level; //Button trigger level reading function
- btn->Button_Trigger_Level = btn_trigger_level; //Button trigger level
- btn->Button_Last_Level = btn->Read_Button_Level(); //Button current level
- btn->Debounce_Time = 0;
-
- RT_DEBUG_LOG(RT_DEBUG_THREAD,("button create success!"));
-
- Add_Button(btn); //Added to the singly linked list when button created
-
- Print_Btn_Info(btn); //printf info
-
- }
- /************************************************************
- * @brief burron trigger events are attach to callback function
- * @param btn:button structure
- * @param btn_event:button events
- * @param btn_callback : Callback handler after the button is triggered.Need user implementation
- * @return RT_NULL
- * @author jiejie
- * @github https://github.com/jiejieTop
- * @date 2018-xx-xx
- * @version v1.0
- ***********************************************************/
- void Button_Attach(Button_t *btn,Button_Event btn_event,Button_CallBack btn_callback)
- {
- if( btn == RT_NULL)
- {
- RT_DEBUG_LOG(RT_DEBUG_THREAD,("struct button is RT_NULL!"));
- }
-
- if(BUTTON_ALL_RIGGER == btn_event)
- {
- for(rt_uint8_t i = 0 ; i < number_of_event-1 ; i++)
- /*A callback function triggered by a button event ,Used to handle button events */
- btn->CallBack_Function[i] = btn_callback;
- }
- else
- {
- btn->CallBack_Function[btn_event] = btn_callback;
- }
- }
- /************************************************************
- * @brief Delete an already created button
- * @param RT_NULL
- * @return RT_NULL
- * @author jiejie
- * @github https://github.com/jiejieTop
- * @date 2018-xx-xx
- * @version v1.0
- * @note RT_NULL
- ***********************************************************/
- void Button_Delete(Button_t *btn)
- {
- struct button** curr;
- for(curr = &Head_Button; *curr;)
- {
- struct button* entry = *curr;
- if (entry == btn)
- {
- *curr = entry->Next;
- }
- else
- {
- curr = &entry->Next;
- }
- }
- }
- /************************************************************
- * @brief Get Button Event Info
- * @param RT_NULL
- * @return RT_NULL
- * @author jiejie
- * @github https://github.com/jiejieTop
- * @date 2018-xx-xx
- * @version v1.0
- ***********************************************************/
- void Get_Button_EventInfo(Button_t *btn)
- {
- for(rt_uint8_t i = 0 ; i < number_of_event-1 ; i++)
- {
- if(btn->CallBack_Function[i] != 0)
- {
- /* print */
- RT_DEBUG_LOG(RT_DEBUG_THREAD,("Button_Event:%d",i));
- }
- }
- }
- /************************************************************
- * @brief Get Button Event
- * @param RT_NULL
- * @return RT_NULL
- * @author jiejie
- * @github https://github.com/jiejieTop
- * @date 2018-xx-xx
- * @version v1.0
- ***********************************************************/
- rt_uint8_t Get_Button_Event(Button_t *btn)
- {
- return (rt_uint8_t)(btn->Button_Trigger_Event);
- }
- /************************************************************
- * @brief Get Button State
- * @param RT_NULL
- * @return RT_NULL
- * @author jiejie
- * @github https://github.com/jiejieTop
- * @date 2018-xx-xx
- * @version v1.0
- ***********************************************************/
- rt_uint8_t Get_Button_State(Button_t *btn)
- {
- return (rt_uint8_t)(btn->Button_State);
- }
- /************************************************************
- * @brief button cycle processing function
- * @param btn:button structure
- * @return RT_NULL
- * @author jiejie
- * @github https://github.com/jiejieTop
- * @date 2018-xx-xx
- * @version v1.0
- * @note This function must be called in a certain period. The recommended period is 20~50ms.
- ***********************************************************/
- void Button_Cycle_Process(Button_t *btn)
- {
- /* Get the current button level */
- rt_uint8_t current_level = (rt_uint8_t)btn->Read_Button_Level();
-
- /* Button level changes, debounce */
- if((current_level != btn->Button_Last_Level)&&(++(btn->Debounce_Time) >= BUTTON_DEBOUNCE_TIME))
- {
- /* Update current button level */
- btn->Button_Last_Level = current_level;
- /* button is pressed */
- btn->Debounce_Time = 0;
-
- /* If the button is not pressed, change the button state to press (first press / double trigger) */
- if(((btn->Button_State == NONE_TRIGGER) || (btn->Button_State == BUTTON_DOUBLE))
- && current_level == btn->Button_Trigger_Level)
- {
- btn->Button_State = BUTTON_DOWM;
- TRIGGER_CB(BUTTON_DOWM);
- }
- //free button
- else if(btn->Button_State == BUTTON_DOWM)
- {
- btn->Button_State = BUTTON_UP;
- TRIGGER_CB(BUTTON_UP);
- RT_DEBUG_LOG(RT_DEBUG_THREAD,("button release"));
- }
- }
-
- switch(btn->Button_State)
- {
- /* button dowm */
- case BUTTON_DOWM :
- {
- if(btn->Button_Last_Level == btn->Button_Trigger_Level)
- {
- /* Support continuous triggering */
- #ifdef CONTINUOS_TRIGGER
- if(++(btn->Button_Cycle) >= BUTTON_CONTINUOS_CYCLE)
- {
- btn->Button_Cycle = 0;
- btn->Button_Trigger_Event = BUTTON_CONTINUOS;
- /* continuous triggering */
- TRIGGER_CB(BUTTON_CONTINUOS);
- RT_DEBUG_LOG(RT_DEBUG_THREAD,("continuous triggering"));
- }
-
- #else
-
- btn->Button_Trigger_Event = BUTTON_DOWM;
-
- /* Update the trigger event before releasing the button as long press */
- if(++(btn->Long_Time) >= BUTTON_LONG_TIME)
- {
- #ifdef LONG_FREE_TRIGGER
-
- btn->Button_Trigger_Event = BUTTON_LONG;
-
- #else
-
- /* Continuous triggering of long press cycles */
- if(++(btn->Button_Cycle) >= BUTTON_LONG_CYCLE)
- {
- btn->Button_Cycle = 0;
- btn->Button_Trigger_Event = BUTTON_LONG;
-
- /* long triggering */
- TRIGGER_CB(BUTTON_LONG);
- }
- #endif
-
- /* Update time overflow */
- if(btn->Long_Time == 0xFF)
- {
- btn->Long_Time = BUTTON_LONG_TIME;
- }
- RT_DEBUG_LOG(RT_DEBUG_THREAD,("Long press"));
- }
-
- #endif
- }
- break;
- }
-
- /* button up */
- case BUTTON_UP :
- {
- /* Trigger click */
- if(btn->Button_Trigger_Event == BUTTON_DOWM)
- {
- /* double click */
- if((btn->Timer_Count <= BUTTON_DOUBLE_TIME)&&(btn->Button_Last_State == BUTTON_DOUBLE))
- {
- btn->Button_Trigger_Event = BUTTON_DOUBLE;
- TRIGGER_CB(BUTTON_DOUBLE);
- RT_DEBUG_LOG(RT_DEBUG_THREAD,("double click"));
- btn->Button_State = NONE_TRIGGER;
- btn->Button_Last_State = NONE_TRIGGER;
- }
- else
- {
- btn->Timer_Count=0;
- /* Detection long press failed, clear 0 */
- btn->Long_Time = 0;
-
- #ifndef SINGLE_AND_DOUBLE_TRIGGER
- /* click */
- TRIGGER_CB(BUTTON_CLICK);
- #endif
- btn->Button_State = BUTTON_DOUBLE;
- btn->Button_Last_State = BUTTON_DOUBLE;
-
- }
- }
-
- else if(btn->Button_Trigger_Event == BUTTON_LONG)
- {
- #ifdef LONG_FREE_TRIGGER
- /* Long press */
- TRIGGER_CB(BUTTON_LONG);
- #else
-
- /* Long press free */
- TRIGGER_CB(BUTTON_LONG_FREE);
- #endif
- btn->Long_Time = 0;
- btn->Button_State = NONE_TRIGGER;
- btn->Button_Last_State = BUTTON_LONG;
- }
-
- #ifdef CONTINUOS_TRIGGER
- /* Press continuously */
- else if(btn->Button_Trigger_Event == BUTTON_CONTINUOS)
- {
- btn->Long_Time = 0;
- /* Press continuously free */
- TRIGGER_CB(BUTTON_CONTINUOS_FREE);
- btn->Button_State = NONE_TRIGGER;
- btn->Button_Last_State = BUTTON_CONTINUOS;
- }
- #endif
-
- break;
- }
-
- case BUTTON_DOUBLE :
- {
- /* Update time */
- btn->Timer_Count++;
- if(btn->Timer_Count>=BUTTON_DOUBLE_TIME)
- {
- btn->Button_State = NONE_TRIGGER;
- btn->Button_Last_State = NONE_TRIGGER;
- }
- #ifdef SINGLE_AND_DOUBLE_TRIGGER
-
- if((btn->Timer_Count>=BUTTON_DOUBLE_TIME)&&(btn->Button_Last_State != BUTTON_DOWM))
- {
- btn->Timer_Count=0;
- TRIGGER_CB(BUTTON_CLICK);
- btn->Button_State = NONE_TRIGGER;
- btn->Button_Last_State = BUTTON_DOWM;
- }
-
- #endif
- break;
- }
- default :
- break;
- }
-
- }
- /************************************************************
- * @brief Traversing the way to scan the button without losing each button
- * @param RT_NULL
- * @return RT_NULL
- * @author jiejie
- * @github https://github.com/jiejieTop
- * @date 2018-xx-xx
- * @version v1.0
- * @note This function is called periodically, it is recommended to call 20-50ms once.
- ***********************************************************/
- void Button_Process(void)
- {
- struct button* pass_btn;
- for(pass_btn = Head_Button; pass_btn != RT_NULL; pass_btn = pass_btn->Next)
- {
- Button_Cycle_Process(pass_btn);
- }
- }
- /************************************************************
- * @brief Search Button
- * @param RT_NULL
- * @return RT_NULL
- * @author jiejie
- * @github https://github.com/jiejieTop
- * @date 2018-xx-xx
- * @version v1.0
- * @note RT_NULL
- ***********************************************************/
- void Search_Button(void)
- {
- struct button* pass_btn;
- for(pass_btn = Head_Button; pass_btn != RT_NULL; pass_btn = pass_btn->Next)
- {
- RT_DEBUG_LOG(RT_DEBUG_THREAD,("button node have %s",pass_btn->Name));
- }
- }
- /************************************************************
- * @brief Handle all button callback functions
- * @param RT_NULL
- * @return RT_NULL
- * @author jiejie
- * @github https://github.com/jiejieTop
- * @date 2018-xx-xx
- * @version v1.0
- * @note Not implemented yet
- ***********************************************************/
- void Button_Process_CallBack(void *btn)
- {
- rt_uint8_t btn_event = Get_Button_Event(btn);
- switch(btn_event)
- {
- case BUTTON_DOWM:
- {
- RT_DEBUG_LOG(RT_DEBUG_THREAD,("Add processing logic for your press trigger"));
- break;
- }
-
- case BUTTON_UP:
- {
- RT_DEBUG_LOG(RT_DEBUG_THREAD,("Add processing logic for your trigger release"));
- break;
- }
-
- case BUTTON_DOUBLE:
- {
- RT_DEBUG_LOG(RT_DEBUG_THREAD,("Add processing logic for your double-click trigger"));
- break;
- }
-
- case BUTTON_LONG:
- {
- RT_DEBUG_LOG(RT_DEBUG_THREAD,("Add processing logic for your long press trigger"));
- break;
- }
-
- case BUTTON_LONG_FREE:
- {
- RT_DEBUG_LOG(RT_DEBUG_THREAD,("Add processing logic for your long press trigger free"));
- break;
- }
-
- case BUTTON_CONTINUOS:
- {
- RT_DEBUG_LOG(RT_DEBUG_THREAD,("Add your continuous trigger processing logic"));
- break;
- }
-
- case BUTTON_CONTINUOS_FREE:
- {
- RT_DEBUG_LOG(RT_DEBUG_THREAD,("Add processing logic for your continuous trigger release"));
- break;
- }
-
- }
- }
- /**************************** The following is the internal call function ********************/
- /************************************************************
- * @brief Copy the specified length string
- * @param RT_NULL
- * @return RT_NULL
- * @author jiejie
- * @github https://github.com/jiejieTop
- * @date 2018-xx-xx
- * @version v1.0
- * @note RT_NULL
- ***********************************************************/
- static char *StrnCopy(char *dst, const char *src, rt_uint32_t n)
- {
- if (n != 0)
- {
- char *d = dst;
- const char *s = src;
- do
- {
- if ((*d++ = *s++) == 0)
- {
- while (--n != 0)
- *d++ = 0;
- break;
- }
- } while (--n != 0);
- }
- return (dst);
- }
- /************************************************************
- * @brief Print button related information
- * @param RT_NULL
- * @return RT_NULL
- * @author jiejie
- * @github https://github.com/jiejieTop
- * @date 2018-xx-xx
- * @version v1.0
- * @note RT_NULL
- ***********************************************************/
- static void Print_Btn_Info(Button_t* btn)
- {
-
- RT_DEBUG_LOG(RT_DEBUG_THREAD,("button struct information:\n\
- btn->Name:%s \n\
- btn->Button_State:%d \n\
- btn->Button_Trigger_Event:%d \n\
- btn->Button_Trigger_Level:%d \n\
- btn->Button_Last_Level:%d \n\
- ",
- btn->Name,
- btn->Button_State,
- btn->Button_Trigger_Event,
- btn->Button_Trigger_Level,
- btn->Button_Last_Level));
- Search_Button();
- }
- /************************************************************
- * @brief Connect buttons with a single linked list
- * @param RT_NULL
- * @return RT_NULL
- * @author jiejie
- * @github https://github.com/jiejieTop
- * @date 2018-xx-xx
- * @version v1.0
- * @note RT_NULL
- ***********************************************************/
- static void Add_Button(Button_t* btn)
- {
- struct button *pass_btn = Head_Button;
-
- while(pass_btn)
- {
- pass_btn = pass_btn->Next;
- }
-
- btn->Next = Head_Button;
- Head_Button = btn;
- }
- #endif
|