📄 headset_buttons.c
字号:
/****************************************************************************Copyright (C) Cambridge Silicon Radio Ltd. 2005-2006Part of BlueLab 3.5.2-releaseFILE NAME headset_buttons.c DESCRIPTION This is the button interpreter for BC4-Headset This file extracts the button messages from the PIO subsystem and figures out the button press type and time. It passes the information to the button manager which is responsible for translating the button press generated into a system eventNOTES*/#include "headset_private.h"#include "headset_buttonmanager.h"#include "headset_buttons.h"#include <stddef.h>#include <csrtypes.h>#include <panic.h>#include <stdlib.h>#include <pio.h>#ifdef DEBUG_BUTTONS#define B_DEBUG(x) DEBUG(x)#else#define B_DEBUG(x) #endif /*the default button durations*/#define B_LONG_TIME_MS 1000#define B_VERY_LONG_TIME_MS 2000#define B_DOUBLE_PRESS_TIME_MS 500#define B_REPEAT_TIME_MS 500typedef enum ButtonsIntMsgTag { B_DOUBLE_TIMER , B_INTERNAL_TIMER , B_REPEAT_TIMER }ButtonsIntMsg_t;#define BUTTON_PIO_DEBOUNCE_NUM_CHECKS 3#define BUTTON_PIO_DEBOUNCE_TIME_MS 5/* LOCAL FUNCTION PROTOTYPES *//****************************************************************************NAME buttonManagerMessageHandlerDESCRIPTION Message handler that receives the button presses and creates the system eventsRETURNS void */void ButtonsMessageHandler ( Task pTask, MessageId pId, Message pMessage ) ;static bool ButtonsWasButtonPressed ( uint16 pOldState , uint16 pNewState) ;static uint16 ButtonsWhichButtonChanged ( uint16 pOldState , uint16 pNewState ) ;static void ButtonsButtonDetected ( BTaskData * pBTask ,uint16 pButtonMask , ButtonsTime_t pTime ) ;static void ButtonsEdgeDetect ( const uint16 pState , BTaskData * pBTask ) ; static void ButtonsLevelDetect ( const uint16 pState , BTaskData * pBTask ) ;/****************************************************************************VARIABLES *//**************************************************************************** FUNCTIONS*//****************************************************************************NAME buttonManagerInit DESCRIPTION Initialises the Button Module parametersRETURNS void*/ void ButtonsInit ( BTaskData *pBTask ){ pBTask->gBOldState = 0x0000 ; pBTask->gBTime = B_SHORT ; pBTask->gBDoubleTap = FALSE ; pBTask->gBDoubleState = 0x0000 ; pBTask->gButtonLevelMask = 0x0000 ; pBTask->gButtonEdgeMask = 0x0000 ; pBTask->gBOldEdgeState = 0x0000 ; pBTask->task.handler = ButtonsMessageHandler; /*connect the underlying PIO task to this task*/ MessagePioTask(&pBTask->task); pBTask->gBLongDuration_ms = B_LONG_TIME_MS; pBTask->gBVeryLongDuration_ms = B_VERY_LONG_TIME_MS; pBTask->gBDoubleDuration_ms = B_DOUBLE_PRESS_TIME_MS; pBTask->gBRepeatDuration_ms = B_REPEAT_TIME_MS; B_DEBUG(("B : Get[%x]\n", PioGet() )) ; }/****************************************************************************NAME ButtonsRegisterButtonsDESCRIPTION Registers buttons contained in the mask so that they will be detected by the button taskRETURNS void */void ButtonsRegisterButtons ( BTaskData *pBTask, uint16 pButtonMask , ButtonTriggerType_t pTrigger ) { switch ( pTrigger ) { case ( ButtonLevelTrigger ): { pBTask->gButtonLevelMask |= pButtonMask ; B_DEBUG(("B :Reg Lvl[%x][%x]\n",pButtonMask , pBTask->gButtonLevelMask)) ; /*reset the state so that no messages are sent*/ pBTask->gBTime = B_INVALID ; /*kick off the messages looking for a power On*/ ButtonsLevelDetect ( PioGet() , pBTask ) ; } break; case ( ButtonEdgeTrigger ): { pBTask->gButtonEdgeMask |= pButtonMask ; B_DEBUG(("B :Reg Edge[%x][%x]\n",pButtonMask , pBTask->gButtonEdgeMask)) ; ButtonsEdgeDetect ( PioGet() , pBTask) ; } break; default: B_DEBUG(("B: reg [%x]?\n",pTrigger)) ; break; } /* Debounce required PIO lines */ PioDebounce(pBTask->gButtonEdgeMask | pBTask->gButtonLevelMask, BUTTON_PIO_DEBOUNCE_NUM_CHECKS, BUTTON_PIO_DEBOUNCE_TIME_MS); }/*************************************************************NAME ButtonsUnRegisterButtonsDESCRIPTION Removes Registered buttons contained in the masks so that they will be detected by the button taskRETURNS void */void ButtonsUnRegisterButtons ( BTaskData *pBTask, uint16 pButtonMask ){ pBTask->gButtonLevelMask &= (0xFFFF - pButtonMask ) ; B_DEBUG(("B :UnReg Lvl[%x][%x]\n",pButtonMask , pBTask->gButtonLevelMask)) ; pBTask->gButtonEdgeMask &= (0xFFFF - pButtonMask ) ; B_DEBUG(("B :UnReg Edge[%x][%x]\n",pButtonMask , pBTask->gButtonEdgeMask)) ;}void ButtonsConfigDurations ( BTaskData *pBTask, uint16 pLong , uint16 pVeryLong , uint16 pDouble , uint16 pRepeat) { /* Range checking performed by Configuration Manager */ B_DEBUG(("B : Dur [%d][%d][%d][%d]\n" , pLong , pVeryLong , pDouble, pRepeat )) ; pBTask->gBLongDuration_ms = pLong; pBTask->gBVeryLongDuration_ms = pVeryLong ; pBTask->gBDoubleDuration_ms = pDouble ; pBTask->gBRepeatDuration_ms = pRepeat ;}/****************************************************************************NAME buttonManagerMessageHandlerDESCRIPTION the button event message handler - converts button events to the system eventsRETURNS void*/void ButtonsMessageHandler ( Task pTask, MessageId pId, Message pMessage ) { BTaskData * lBTask = (BTaskData*)pTask ; /*the message if there is one*/ const MessagePioChanged * lMessage = ( const MessagePioChanged * ) (pMessage ) ; B_DEBUG(("B :BMess \n")) ; switch ( pId ) { case MESSAGE_PIO_CHANGED : { ButtonsLevelDetect ( (uint16) lMessage->state , lBTask ) ; ButtonsEdgeDetect ( (uint16) lMessage->state , lBTask ) ; } break ; case B_DOUBLE_TIMER: /*if we have reached here, then a double timer has been received*/ B_DEBUG(("B : Double[%x][%x]\n", lBTask->gBDoubleState , B_SHORT_SINGLE)) ; lBTask->gBDoubleTap = FALSE ; /*indicate that a short button was pressed and it did not become a double press */ ButtonsButtonDetected ( lBTask, lBTask->gBDoubleState , B_SHORT_SINGLE ); break ; case B_INTERNAL_TIMER: /*if we have reached here, then the buttons have been held longer than one of the timed messages*/ B_DEBUG(("B : Timer\n")) ; if ( lBTask->gBTime == B_LONG ) { lBTask->gBTime = B_VERY_LONG ; /*notify the app that the timer has expired*/ MessageSend( getAppTask() , EventVLongTimer , 0 ) ; }else { /*notify the app that the timer has expired*/ MessageSend( getAppTask() , EventLongTimer , 0 ) ; lBTask->gBTime = B_LONG ; } /*indicate that we have received a message */ ButtonsButtonDetected ( lBTask, lBTask->gBOldState , lBTask->gBTime ); break ; case B_REPEAT_TIMER: /*if we have reached here, the repeat time has been reached so send a new message*/ B_DEBUG(("B : Repeat [%x][%x]\n", lBTask->gBOldState , B_REPEAT )) ; /*send another repeat message*/ MessageSendLater ( &lBTask->task , B_REPEAT_TIMER , 0 , lBTask->gBRepeatDuration_ms ) ; ButtonsButtonDetected ( lBTask, lBTask->gBOldState , B_REPEAT ); break; default : B_DEBUG(("B : ?[%x]\n",pId)) ; break ; }}/****************************************************************************NAME ButtonsWasButtonPressed DESCRIPTION helper method - returns true if a buton was pressedRETURNS bool*/ static bool ButtonsWasButtonPressed ( uint16 pOldState , uint16 pNewState){ bool lWasButtonPressed = FALSE ; uint16 lButton = ButtonsWhichButtonChanged ( pOldState , pNewState ) ; if ( ( lButton & pNewState ) != 0 ) { lWasButtonPressed = TRUE ; } /* B_DEBUG(("B : Was[%x]\n", lWasButtonPressed)) ; */ return lWasButtonPressed ;}/****************************************************************************NAME ButtonsWhichButtonChanged DESCRIPTION helper method - returns mask ofwhich button changedRETURNS uint16*/ static uint16 ButtonsWhichButtonChanged ( uint16 pOldState , uint16 pNewState ){ uint16 lWhichButton = 0 ; lWhichButton = (pNewState ^ pOldState ) ; /* B_DEBUG(("B : Whi[%x] \n", lWhichButton)) ; */ return lWhichButton ;}/****************************************************************************NAME ButtonsButtonDetected DESCRIPTION function to handle a button press - informs button manager of a change currently makes direct call - may want to use message handling (tasks)RETURNS uint16*/ static void ButtonsButtonDetected ( BTaskData * pBTask, uint16 pButtonMask , ButtonsTime_t pTime ){ if( pButtonMask == 0 ) {/* MessageCancelAll ( &pBTask->task , B_INTERNAL_TIMER ) ;*/ MessageCancelAll ( &pBTask->task , B_REPEAT_TIMER ) ; } else { BMButtonDetected ( pButtonMask , pTime ) ; } }/****************************************************************************NAME ButtonsLevelDetect DESCRIPTION function to detect level changes of buttons / multiple buttons. RETURNS void*/ static void ButtonsLevelDetect ( const uint16 pState , BTaskData * pBTask ) { uint16 lNewState = 0x0000; /*we have an indication from the PIO subsytem that a PIO has changed value*/ lNewState = (int) (pState & (pBTask->gButtonLevelMask) ) ; B_DEBUG(("B| : [%x][%x]\n", pState , (pBTask->gButtonLevelMask) )) ; B_DEBUG(("B| : [%x][%x]\n", pBTask->gBOldState , lNewState )) ; if ( ButtonsWasButtonPressed( pBTask->gBOldState , lNewState ) ) { /*cancel all previously timed messages*/ MessageCancelAll ( &pBTask->task , B_INTERNAL_TIMER ) ; MessageCancelAll ( &pBTask->task , B_REPEAT_TIMER ) ; MessageCancelAll ( &pBTask->task , B_DOUBLE_TIMER ) ; /* send new timed messages*/ MessageSendLater ( &pBTask->task , B_INTERNAL_TIMER , 0 , pBTask->gBLongDuration_ms ) ; MessageSendLater ( &pBTask->task , B_INTERNAL_TIMER , 0 , pBTask->gBVeryLongDuration_ms ) ; MessageSendLater ( &pBTask->task , B_REPEAT_TIMER , 0 , pBTask->gBRepeatDuration_ms ) ; /*having restrted the timers, reset the time*/ pBTask->gBTime = B_SHORT ; } else /*button was released or was masked out*/ { /*it was only a released if there was a button actually pressed last time around - buttons we have masked out still end up here but no state changes are made */ if ( pBTask->gBOldState != 0 ) { /*if we have had a double press in the required time and the button pressed was the same as this one*/ if ( (pBTask->gBDoubleTap == TRUE ) && (pBTask->gBOldState == pBTask->gBDoubleState ) ) { pBTask->gBTime = B_DOUBLE ; /*reset the double state*/ pBTask->gBDoubleState = 0x0000 ; pBTask->gBDoubleTap = FALSE ; ButtonsButtonDetected ( pBTask , pBTask->gBOldState , B_DOUBLE ); } /*only send a message if it was a short one - long / v long /double handled elsewhere*/ if ( (pBTask->gBTime == B_SHORT ) ) { ButtonsButtonDetected ( pBTask , pBTask->gBOldState , B_SHORT ); /*store the double state*/ pBTask->gBDoubleState = pBTask->gBOldState ; pBTask->gBDoubleTap = TRUE ; /*start the double timer - only applicable to a short press*/ MessageSendLater ( &pBTask->task , B_DOUBLE_TIMER , 0 ,pBTask->gBDoubleDuration_ms ) ; } else if ( (pBTask->gBTime == B_LONG) ) { ButtonsButtonDetected ( pBTask , pBTask->gBOldState , B_LONG_RELEASE ); } else if ( (pBTask->gBTime == B_VERY_LONG) ) { ButtonsButtonDetected ( pBTask , pBTask->gBOldState , B_VERY_LONG_RELEASE ); } if (pBTask->gBTime != B_INVALID) { MessageCancelAll ( &pBTask->task , B_INTERNAL_TIMER) ; MessageCancelAll ( &pBTask->task , B_REPEAT_TIMER ) ; } /*removing this allows all releases to generate combination presses is this right?*/ if ( !lNewState ) { pBTask->gBTime = B_INVALID ; } } } pBTask->gBOldState = lNewState ;} /****************************************************************************NAME EdgeDetect DESCRIPTION function to detect edge changes of buttons / multiple buttons. RETURNS void*/ static void ButtonsEdgeDetect ( const uint16 pState , BTaskData * pBTask ) { uint16 lNewState = 0x0000 ; uint16 lButton = 0x0000 ; /*what has changed */ lNewState = (int) ( pState & (pBTask->gButtonEdgeMask) ) ; lButton = ButtonsWhichButtonChanged( pBTask->gBOldEdgeState , lNewState ) ; B_DEBUG(("BA: [%x][%x][%x]\n", pBTask->gBOldEdgeState , lNewState , pBTask->gButtonEdgeMask )) ; B_DEBUG(("BB: [%x][%x][%x]\n", lNewState , lButton , (lNewState & lButton) )) ; /*if a button has changed*/ if ( lButton ) { /*determine which edge has been received and process accordingly*/ if ( lNewState & lButton ) { ButtonsButtonDetected ( pBTask , lButton , B_LOW_TO_HIGH ) ; } else { ButtonsButtonDetected ( pBTask , lButton , B_HIGH_TO_LOW ) ; } } /*remember the last state*/ pBTask->gBOldEdgeState = lNewState;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -