/**************************************************************************** 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 }
/**************************************************************************** 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")) ; }
/**************************************************************************** DESCRIPTION function to detect edge changes of buttons / multiple buttons. */ static void ButtonsCheckDetection(uint16 CapSenseState, uint32 PioState) { ButtonsTaskData * lBTask = theSink.theButtonsTask ; /* take the current capacitive touch state and pio state and translate into a uint32 input state used for checking button presses */ uint32 lInputState = ButtonsTranslate(CapSenseState, PioState); B_DEBUG(("But CheckDet: Inputs: Cap[%x] PIO[%lx] Inputs[%lx] OldState[%lx]\n", CapSenseState , PioState , lInputState, lBTask->gBOldInputState)) ; B_DEBUG(("But CheckDet: Masks: Edge [%lx] Lev [%lx]\n",lBTask->gPerformInputEdgeCheck, lBTask->gPerformInputLevelCheck)); /* when an input 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->gPerformInputEdgeCheck & lInputState) || (lBTask->gPerformInputEdgeCheck & lBTask->gBOldInputState)) { /* check for a valid edge transition against current pio states masked with edge configured pios and perform appropriate action */ ButtonsEdgeDetect ( lInputState, 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->gPerformInputLevelCheck & lInputState ) || (lBTask->gPerformInputLevelCheck & lBTask->gBOldInputState)) { /* perform a level detection, this call uses a number of messages and is quite slow to process */ ButtonsLevelDetect ( lInputState, lBTask) ; } #ifdef ENABLE_GAIA gaiaReportPioChange(PioState); #endif /* update last button state for next time around */ lBTask->gBOldInputState = lInputState; lBTask->gOldPIOState = PioState; }
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 ; } }