⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 headset_buttons.c

📁 bluelab的一个很好的例程
💻 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 + -