Пример #1
0
/****************************************************************************
DESCRIPTION
    Called after the configuration has been read and will trigger buttons events
    if a pio has been pressed or held whilst the configuration was still being loaded
    , i.e. the power on button press    
*/
void ButtonsCheckForChangeAfterInit(void)
{        
    uint32 input_state; /* contains translated pio and capsense bits, format is inputs */

    ButtonsTaskData * lButtonsTask = theSink.theButtonsTask ;
      
    lButtonsTask->gBTime = B_INVALID ;   

    /* translate the pio and capsense bits into 'input' bits mask */
#ifdef ENABLE_CAPSENSE
    input_state = ButtonsTranslate(lButtonsTask->gOldCapState, (((PIOGET()^theSink.conf1->PIOIO.pio_invert) | CHARGER_VREG_VALUE | CHARGER_CONNECT_VALUE)));
#else    
    input_state = ButtonsTranslate(0, (((PIOGET()^theSink.conf1->PIOIO.pio_invert) | CHARGER_VREG_VALUE | CHARGER_CONNECT_VALUE)));
#endif
    /* perform a level detect looking for transistion of recently added button definition, mask inputs 
       against level configured inputs to prevent false button press indications */
    ButtonsLevelDetect ( (input_state & lButtonsTask->gPerformInputLevelCheck) , lButtonsTask ) ;
    
    /* perform an edge detect looking for transistion of recently added button definition, mask inputs 
       against edge configured inputs to prevent false button press indications */
    ButtonsEdgeDetect ( (input_state & lButtonsTask->gPerformInputEdgeCheck) , lButtonsTask) ;
    
    /* store current input states in order to be able to detect the transition of an input (pio or capsense)
       in the button handler */
    lButtonsTask->gBOldInputState = input_state;

    /* Debounce required PIO lines */
    if(!PioCommonDebounce((lButtonsTask->gButtonPIOLevelMask & ~(VREG_PIN_MASK|CHG_PIN_MASK)),  
                           lButtonsTask->button_config->debounce_number, 
                           lButtonsTask->button_config->debounce_period_ms ))
    {
        B_DEBUG(("B: **** ERROR **** PIO NOT AVAILABLE = 0x%lx\n",input_state)) ;
#ifdef DEBUG_BUTTONS
        Panic();
#endif

    }
    
    ChargerDebounce( (CHARGER_VREG_EVENT|CHARGER_CONNECT_EVENT), lButtonsTask->button_config->debounce_number, lButtonsTask->button_config->debounce_period_ms );
    B_DEBUG(("B: initial buttoncheck\n")) ;
    
} 
Пример #2
0
/****************************************************************************
DESCRIPTION
 	Called after the configuration has been read and will trigger buttons events
    if a pio has been pressed or held whilst the configuration was still being loaded
    , i.e. the power on button press    
*/
void ButtonsCheckForChangeAfterInit(void)
{        
    uint32 pio_state;

    ButtonsTaskData * lButtonsTask = theHeadset.theButtonsTask ;
      
    lButtonsTask->gBTime = B_INVALID ; 
    
    {
        /* get 32 bit pio state for BC5 onwards chips */
        pio_state = (((PIOGET() & 0xffff) | CHARGER_VREG_VALUE | CHARGER_CONNECT_VALUE)) ;
        
        /* perform a level detect looking for transistion of recently added button definition, mask pio's 
           against level configured pios to prevent false butotn press indications */
        ButtonsLevelDetect ( (pio_state & lButtonsTask->gPerformLevelCheck) , lButtonsTask ) ;
    
        /* perform an edge detect looking for transistion of recently added button definition, mask pio's 
           against edge configured pios to prevent false button press indications */
        ButtonsEdgeDetect ( (pio_state & lButtonsTask->gPerformEdgeCheck) , lButtonsTask) ;
    }
    
    /* store current set pio state in order to be able to detect the transition of a PIO in the button handler */
    lButtonsTask->gOldPioState = pio_state;
            
    /* Debounce required PIO lines */
    pio_state = PioDebounce32((0xFFFF & lButtonsTask->gButtonLevelMask),  /* mask off upper 16 bits */
                              lButtonsTask->button_config->debounce_number, 
                              lButtonsTask->button_config->debounce_period_ms );    
    
    /* check whether it has been possible to select the use of PIOs specified, if it was not possible
       to use all the PIOs specified due to a PIO being assigned a different function by PSKEY then none 
       of the PIOs will now work so mask out the unavailable PIO and assign the PIOs that are available
       for receiving change notifications */
    if(pio_state)
    {
        /* mask out the unavailable PIOs and register those PIOs that are available for receiving change events */
        PioDebounce32((0xFFFF & lButtonsTask->gButtonLevelMask & ~pio_state),  /* mask off upper 16 bits */
                              lButtonsTask->button_config->debounce_number, 
                              lButtonsTask->button_config->debounce_period_ms );           

        B_DEBUG(("B: **** ERROR **** PIO NOT AVAILABLE = 0x%lx\n",pio_state)) ;

#ifdef DEBUG_BUTTONS
        Panic();
#endif
    }

#ifdef BHC612_
	ChargerDebounce( (CHARGER_VREG_EVENT|CHARGER_CONNECT_EVENT), 4, 250 );
#else
    ChargerDebounce( (CHARGER_VREG_EVENT|CHARGER_CONNECT_EVENT), lButtonsTask->button_config->debounce_number, lButtonsTask->button_config->debounce_period_ms );
#endif    
} 
Пример #3
0
static void ButtonsMessageHandler ( Task pTask, MessageId pId, Message pMessage ) 
{   
    ButtonsTaskData * lBTask = (ButtonsTaskData*)pTask ;

    B_DEBUG(("B:Message\n")) ;
    switch ( pId )
    {
	    case MESSAGE_PIO_CHANGED : 
        {
            const MessagePioChanged * lMessage = ( const MessagePioChanged * ) (pMessage ) ;
            uint32 lNewPioState = (uint32)( lMessage->state | CHARGER_VREG_VALUE | CHARGER_CONNECT_VALUE) ;
            
            B_DEBUG(("B:BMH - PIO_CHANGE: %x %x\n",lMessage->state16to31, lMessage->state)) ;
            
        
            /* when a pio is configured for an edge detect only there is significant performance gain to be had
               by only doing an edge detect call and not a level detect. To do this use a previously set edge
               detect mask and check this against the current pio being reported. Also need to check if a previously
               set PIO has now been removed and check for the edge transition once again. */
            if((lBTask->gPerformEdgeCheck & lNewPioState) ||
               (lBTask->gPerformEdgeCheck & lBTask->gOldPioState))
            {
                /* check for a valid edge transition against current pio states masked with edge configured pios
                   and perform appropriate action */                
                ButtonsEdgeDetect  ( (uint32)( lNewPioState & lBTask->gPerformEdgeCheck), lBTask ) ;
            }          
            
            /* only do a level detect call which is vm/messaging intensive when a pio has been configured as 
               short or long or very long or very very long, i.e. not rising or falling */
            if((lBTask->gPerformLevelCheck & lNewPioState ) ||
               (lBTask->gPerformLevelCheck & lBTask->gOldPioState))
            {
                /* perform a level detection, this call uses a number of messages and is quite slow to process */
                ButtonsLevelDetect ( ((uint32)lNewPioState & lBTask->gPerformLevelCheck) , lBTask) ;            
            }         
            
            /* store current set pio state in order to be able to detect the transition of a PIO configured as edge 
               detect only */
            lBTask->gOldPioState = lNewPioState ;
        
        }
    	break ;
        
        case MESSAGE_CHARGER_CHANGED:
	    {
		    const MessageChargerChanged *m = (const MessageChargerChanged *) (pMessage ) ;			
         
            /* when a charger or vreg change event is detectecd perform both an edge and level detection
               passing in only those approriately masked pios for edge or level configured buttons */
            ButtonsLevelDetect ( (((uint32)m->vreg_en_high << VREG_PIN) | ((uint32)m->charger_connected << CHG_PIN) | PIOGET()) & lBTask->gPerformLevelCheck , lBTask) ;           
            ButtonsEdgeDetect  ( (((uint32)m->vreg_en_high << VREG_PIN) | ((uint32)m->charger_connected << CHG_PIN) | PIOGET()) & lBTask->gPerformEdgeCheck , lBTask ) ;           
	    }
        break;
   
    	case B_DOUBLE_TIMER:
		{
				/*if we have reached here, then a double timer has been received*/
         	B_DEBUG(("B:Double[%lx][%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")) ;
            
            /* an internal timer has triggered which was initiated from the level detect function call */
        	if ( lBTask->gBTime == B_VERY_LONG )
        	{
                /* update timer state flag */
                lBTask->gBTime = B_VERY_VERY_LONG ;                
        	}
			/* a long press timer event has triggered */
            else if ( lBTask->gBTime == B_LONG )
        	{
                /* don't send very very long timer message until needed, i.e. very_long timer expired */
                MessageSendLater ( &lBTask->task , B_INTERNAL_TIMER , 0 ,  (lBTask->button_config->very_very_long_press_time - lBTask->button_config->very_long_press_time ) ) ;                   
                /* update tiemr state flag */
            	lBTask->gBTime = B_VERY_LONG ;
               	/*notify the app that the timer has expired*/
            	MessageSend( &theHeadset.task , EventVLongTimer , 0 ) ;    
        	}
			/* the first timer event triggered from the level detect call */
            else
        	{
                /* only send very long message when long timer expired to save messaging.                 */
                MessageSendLater ( &lBTask->task , B_INTERNAL_TIMER , 0 , (lBTask->button_config->very_long_press_time - lBTask->button_config->long_press_time)) ;
               	/*notify the app that the timer has expired*/
            	MessageSend( &theHeadset.task , 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[%lx][%x]\n", lBTask->gBOldState , B_REPEAT  )) ;
        
        	/*send another repeat message*/
        	MessageSendLater ( &lBTask->task , B_REPEAT_TIMER , 0 ,  lBTask->button_config->repeat_time ) ; 

        	ButtonsButtonDetected ( lBTask, lBTask->gBOldState , B_REPEAT ); 
		}
        break;
    	default :
           B_DEBUG(("B:?[%x]\n",pId)) ; 
        break ;
    }
}
Пример #4
0
static void ButtonsMessageHandler ( Task pTask, MessageId pId, Message pMessage ) 
{   
    ButtonsTaskData * lBTask = (ButtonsTaskData*)pTask ;

    B_DEBUG(("B:Message\n")) ;
    switch ( pId )
    {
#ifdef ENABLE_CAPSENSE
        
        /* delay handling of messages until capsense hardware has settled down */
        case B_MESSAGE_CAPSENSE_ENABLE :
        {
            /* connect the cap sense task to this task */    
            MessageCapsenseTask(&lBTask->task);
        }
        break;

        /* indication of a change of one of the capacitive touch sensors */
        case MESSAGE_CAPSENSE_CHANGED : 
        {
            uint8 i;
            const MessageCapsenseChanged * lMessage = ( const MessageCapsenseChanged * ) (pMessage ) ;
            uint16 CurrentCapState = lBTask->gOldCapState;
                      
            B_DEBUG(("B:Cap - Events = %x pad = %x dir = %x\n",lMessage->num_events,lMessage->event[0].pad,lMessage->event[0].direction)) ;

            /* the cap sense changed message may contain more than one button press, check for other
               presses or releases */
            for(i=0;i<lMessage->num_events;i++)
            {
                /* update the state of any sensor changes, direction is inverted, 0 = down, 1 = up  */
                if(lMessage->event[i].direction == CAPSENSE_EVENT_POS)
                    CurrentCapState |= (1<<(lMessage->event[i].pad));
                /* due to the fact that the fw will not report multiple press need to maintain
                    which touch sensors are up and which are down and set/reset appropriately */
                else
                    CurrentCapState &= ~(1<<(lMessage->event[i].pad));                
                        
                /* as the touch sensors as less effective when releasing, increase sesitivity 
                   when button indicates pressed to accurately detect the release event */
                if(lMessage->event[i].direction == CAPSENSE_EVENT_POS)
                {
                   if(!CapsenseConfigurePad(lMessage->event[i].pad, CAPSENSE_SET_TRIGGER_LEVEL, BM_CAP_SENSOR_HIGH_SENSITIVITY))
                       B_DEBUG(("B:Cap - invalid threshold %d\n",BM_CAP_SENSOR_LOW_SENSITIVITY));

                   /* button gone down, it is possible to record the time in mS at which the 
                      button went down, this can be used to accurately determine how long the 
                      button was held down for */                   
                   B_DEBUG(("B:Cap - Down Time %x = %ld mS\n",i,(uint32)lMessage->event[i].time_ms)) ;
                }
                /* return to original sensitivity when releasing button */                
                else
                {
                   if(!CapsenseConfigurePad(lMessage->event[i].pad, CAPSENSE_SET_TRIGGER_LEVEL, BM_CAP_SENSOR_LOW_SENSITIVITY))
                       B_DEBUG(("B:Cap - invalid threshold %d\n",BM_CAP_SENSOR_LOW_SENSITIVITY));
                       
                   /* button gone up, the time in mS can be used to get accurate duration information */
                   B_DEBUG(("B:Cap - Up Time %x = %ld mS\n",i,(uint32)lMessage->event[i].time_ms)) ;
                }
            }      
            
            B_DEBUG(("B:Cap - state = %x\n",CurrentCapState)) ;

            /* check whether the sensor status change requires an event to be generated */
            ButtonsCheckDetection(CurrentCapState, lBTask->gOldPIOState);
            
            /* update the last state value */
            lBTask->gOldCapState = CurrentCapState;
        }
        break;
#endif  
        
        case MESSAGE_PIO_CHANGED : 
        {
            const MessagePioChanged * lMessage = ( const MessagePioChanged * ) (pMessage ) ;
            /* get current pio state, eor with pio invert mask  */
            uint32 lNewPioState = (uint32)(theSink.conf1->PIOIO.pio_invert ^ (( lMessage->state | CHARGER_VREG_VALUE | CHARGER_CONNECT_VALUE) | (((uint32)lMessage->state16to31)<<16)));
            
            B_DEBUG(("B:BMH - PIO_CHANGE: %x %x\n",lMessage->state16to31, lMessage->state)) ;
            
#ifdef ENABLE_CAPSENSE
 
            /* check whether the pio status change requires an event to be generated */
            ButtonsCheckDetection(lBTask->gOldCapState, lNewPioState);
#else
            /* check whether the pio status change requires an event to be generated */
            ButtonsCheckDetection(0, lNewPioState);
#endif
        }
        break ;
        
        case MESSAGE_CHARGER_CHANGED:
        {
            const MessageChargerChanged *m = (const MessageChargerChanged *) (pMessage ) ;          
         
            B_DEBUG(("B:BMH - CHG_CHANGE: %lx\n",(((uint32)m->vreg_en_high << VREG_PIN) | ((uint32)m->charger_connected << CHG_PIN) | (PIOGET()^theSink.conf1->PIOIO.pio_invert)))) ;

            /* when a charger or vreg change event is detectecd perform both an edge and level detection
               passing in only those approriately masked pios for edge or level configured buttons */
                        /* check whether the pio status change requires an event to be generated */
#ifdef ENABLE_CAPSENSE
            ButtonsCheckDetection(lBTask->gOldCapState, (((uint32)m->vreg_en_high << VREG_PIN) | ((uint32)m->charger_connected << CHG_PIN) | (PIOGET()^theSink.conf1->PIOIO.pio_invert)));
#else
            ButtonsCheckDetection(0, (((uint32)m->vreg_en_high << VREG_PIN) | ((uint32)m->charger_connected << CHG_PIN) | (PIOGET()^theSink.conf1->PIOIO.pio_invert)));
#endif            
        }
        break;
   
        case B_MULTIPLE_TIMER:
        {
                /*if we have reached here, then a double timer has been received*/
            B_DEBUG(("B:Double[%lx][%x]\n", lBTask->gBMultipleState , B_SHORT_SINGLE)) ;
    
            /* when the multiple press timer has expired, check to see if a double press was
               made and if so indicate it */
            if(lBTask->gBTapCount == DOUBLE_PRESS)
                ButtonsButtonDetected ( lBTask , (lBTask->gBMultipleState & lBTask->gPerformInputLevelCheck) , B_DOUBLE  );                 
            /* no double press and no triple press, therefore indicate as a short single press */            
            else            
                ButtonsButtonDetected ( lBTask, (lBTask->gBMultipleState & lBTask->gPerformInputLevelCheck), B_SHORT_SINGLE );                        
            
            /* reset the multiple button press count */
            lBTask->gBTapCount = 0 ;            
            lBTask->gBMultipleState = 0x0000;
        } 
        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")) ;

            /* since a long/vlong or vvlong has been triggered, cancel any pending double press checks */
            lBTask->gBMultipleState = 0x0000 ;
            lBTask->gBTapCount = 0 ;
            MessageCancelAll ( &lBTask->task , B_MULTIPLE_TIMER ) ;           

            /* an internal timer has triggered which was initiated from the level detect function call */
            if ( lBTask->gBTime == B_VERY_LONG )
            {
                /* update timer state flag */
                lBTask->gBTime = B_VERY_VERY_LONG ;                
            }
            /* a long press timer event has triggered */
            else if ( lBTask->gBTime == B_LONG )
            {
                /* don't send very very long timer message until needed, i.e. very_long timer expired */
                MessageSendLater ( &lBTask->task , B_INTERNAL_TIMER , 0 ,  (lBTask->button_config->very_very_long_press_time - lBTask->button_config->very_long_press_time ) ) ;                   
                /* update tiemr state flag */
                lBTask->gBTime = B_VERY_LONG ;
                /*notify the app that the timer has expired*/
                MessageSend( &theSink.task , EventSysVLongTimer , 0 ) ;    
            }
            /* the first timer event triggered from the level detect call */
            else
            {
                /* only send very long message when long timer expired to save messaging.                 */
                MessageSendLater ( &lBTask->task , B_INTERNAL_TIMER , 0 , (lBTask->button_config->very_long_press_time - lBTask->button_config->long_press_time)) ;
                /*notify the app that the timer has expired*/
                MessageSend( &theSink.task , EventSysLongTimer , 0 ) ;    
                lBTask->gBTime = B_LONG ;
            }    
            /*indicate that we have received a message */
            ButtonsButtonDetected ( lBTask, (lBTask->gBOldInputState & lBTask->gPerformInputLevelCheck) , 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[%lx][%x]\n", lBTask->gBOldInputState , B_REPEAT  )) ;
            
            /*send another repeat message*/
            MessageSendLater ( &lBTask->task , B_REPEAT_TIMER , 0 ,  lBTask->button_config->repeat_time ) ; 

            ButtonsButtonDetected ( lBTask, (lBTask->gBOldInputState & lBTask->gPerformInputLevelCheck) , B_REPEAT ); 
        }
        break;
        default :
           B_DEBUG(("B:?[%x]\n",pId)) ; 
        break ;
    }
}