📄 headset_buttons.c
字号:
/****************************************************************************
Copyright (C) Cambridge Silicon Radio Ltd. 2005
FILE 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 event
NOTES
*/
#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 500
typedef 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
buttonManagerMessageHandler
DESCRIPTION
Message handler that receives the button presses and creates the system events
RETURNS
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 parameters
RETURNS
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
ButtonsRegisterButtons
DESCRIPTION
Registers buttons contained in the mask so that they will be detected by
the button task
RETURNS
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
ButtonsUnRegisterButtons
DESCRIPTION
Removes Registered buttons contained in the masks so that they will be detected by
the button task
RETURNS
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
buttonManagerMessageHandler
DESCRIPTION
the button event message handler - converts button events to the system events
RETURNS
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 pressed
RETURNS
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 changed
RETURNS
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 + -