📄 headset_leds.c
字号:
/****************************************************************************
Copyright (C) Cambridge Silicon Radio Ltd. 2004
FILE NAME
headset_LEDs.c
DESCRIPTION
Module responsible for managing the LED outputs and the pios
configured as led outputs
*/
#include "headset_leds.h"
#include "headset_private.h"
#include "headset_LEDmanager.h"
#include "headset_statemanager.h"
#include "headset_pio.h"
#include <panic.h>
#include <stddef.h>
#ifdef DEBUG_LEDS
#define LED_DEBUG(x) DEBUG(x)
#else
#define LED_DEBUG(x)
#endif
#define LED_ON TRUE
#define LED_OFF FALSE
#define LEDS_STATE_START_DELAY_MS 300
/*internal message handler for the LED callback messages*/
static void LedsMessageHandler( Task task, MessageId id, Message message ) ;
/*helper functions for the message handler*/
static uint16 LedsApplyFilterToTime ( LedTaskData * pLEDTask , uint16 pTime ) ;
static bool LedsGetLEDStateFromPattern ( LedTaskData * pLEDTask , const LEDPattern_t * pPattern , const LEDActivity_t * pLED ) ;
static LEDColour_t LedsGetPatternColour ( LedTaskData * pLEDTask , const LEDPattern_t * pPattern ) ;
/*helper functions to change the state of LED pairs depending on the pattern being played*/
static void LedsTurnOffLEDPair ( LedTaskData * pLEDTask , LEDPattern_t * pPattern, bool pUseOveride ) ;
static void LedsTurnOnLEDPair ( LedTaskData * pLEDTask , LEDPattern_t * pPattern , LEDActivity_t * pLED );
/*method to complete an event*/
static void LedsEventComplete ( LedTaskData * pLEDTask, LEDActivity_t * pPrimaryLed , LEDActivity_t * pSecondaryLed ) ;
/*method to indicate that an event has been completed*/
static void LedsSendEventComplete ( headsetEvents_t pEvent , bool pPatternCompleted ) ;
/*filter enable - check methods*/
static bool LedsIsFilterEnabled ( LedTaskData * pLEDTask , uint16 pFilter ) ;
static void LedsEnableFilter ( LedTaskData * pLEDTask , uint16 pFilter , bool pEnable) ;
static void LedsHandleOverideLED ( LedTaskData * pLEDTask , bool pOnOrOff ) ;
static void LedsCancelStateIndications ( LedTaskData * pLedTask ) ;
static void LedsCancelEventIndications ( LedTaskData * pLEDTask ) ;
/***********************************************************************/
static bool gFollowing = FALSE ;
static bool LedsCheckFiltersForLEDFollower( LedTaskData * pLEDTask ) ;
static uint16 LedsGetLedFollowerRepeatTimeLeft( LedTaskData * pLEDTask , LEDPattern_t* pPattern) ;
static uint16 LedsGetFollowerPin( LedTaskData * pLEDTask ) ;
static uint16 LedsGetLedFollowerStartDelay( LedTaskData * pLEDTask ) ;
/***********************************************************************/
void LedsInit ( LedTaskData * pTask )
{
/*Set the callback handler for the task*/
pTask->task.handler = LedsMessageHandler ;
pTask->gCurrentlyIndicatingEvent = FALSE ;
}
/****************************************************************************
NAME
LedsIndicateEvent
DESCRIPTION
THis function starts an event notification. It overides any prior ent notification acting on the same PIO
It also overides any state notification on the same PIO. If a state indication is happening on a different pio,
this will be allowed to continue.
RETURNS
void
*/
void LedsIndicateEvent ( LedTaskData * pLEDTask , headsetEvents_t pEvent )
{
uint16 lPrimaryLED = 0;
uint16 lSecondaryLED = 0;
uint16 lEventIndex = pEvent - EVENTS_EVENT_BASE ;
/*get the event and start the display*/
lPrimaryLED = pLEDTask->gEventPatterns[lEventIndex]->LED_A;
lSecondaryLED = pLEDTask->gEventPatterns[lEventIndex]->LED_B;
LED_DEBUG(("LM : Ev LED [%x]i[%x] ", pEvent , lEventIndex )) ;
LMPrintPattern ( pLEDTask->gEventPatterns [lEventIndex] ) ;
/*if the PIO we want to use is currently indicating an event then do interrupt the event*/
MessageCancelAll ( &pLEDTask->task, lPrimaryLED ) ;
MessageCancelAll ( &pLEDTask->task, lSecondaryLED ) ;
/*cancel all led state indications*/
LedsCancelStateIndications ( pLEDTask ) ;
/* - need to set the LEDS to a known state before starting the pattern*/
LedsTurnOffLEDPair ( pLEDTask , pLEDTask->gEventPatterns[lEventIndex] , TRUE) ;
/*now set up and start the event indication*/
LedsSetLedActivity ( &pLEDTask->gActiveLEDS[lPrimaryLED] , IT_EventIndication , lEventIndex ) ;
/*Set the Alternative LED up with the same info*/
LedsSetLedActivity ( &pLEDTask->gActiveLEDS[lSecondaryLED] , IT_EventIndication , lEventIndex ) ;
/*if we just want to set a pin as an output (numFlashes == 0) - then dont send a message*/
LED_DEBUG(("LM : NF[%x]\n" , pLEDTask->gEventPatterns [ lEventIndex ]->NumFlashes )) ;
if ( pLEDTask->gEventPatterns [ lEventIndex ]->NumFlashes == 0 )
{
/*set the pins on or off as required*/
if ( pLEDTask->gEventPatterns [ lEventIndex ]->OnTime > 0 )
{
LED_DEBUG(("LM : PIO_ON\n")) ;
LedsTurnOnLEDPair ( pLEDTask , pLEDTask->gEventPatterns [ lEventIndex ] , &pLEDTask->gActiveLEDS[lPrimaryLED] ) ;
}
else if ( pLEDTask->gEventPatterns [ lEventIndex ]->OffTime > 0 )
{
LED_DEBUG(("LM : PIO_OFF\n")) ;
LedsTurnOffLEDPair ( pLEDTask , pLEDTask->gEventPatterns [ lEventIndex ] ,TRUE) ;
/*If we are turning a pin off the revert to state indication*/
LedsEventComplete ( pLEDTask, &pLEDTask->gActiveLEDS[lPrimaryLED] , &pLEDTask->gActiveLEDS[lSecondaryLED] ) ;
}
}
else
{ /*start the pattern indication*/
/*All messages are handled via the primary LED*/
MessageSend (&pLEDTask->task , lPrimaryLED , 0 ) ;
pLEDTask->gCurrentlyIndicatingEvent = TRUE ;
}
}
/****************************************************************************
NAME
LedsCheckForFilter
DESCRIPTION
This function checksif a filter has been configured for the given event,
if it has then activates / deactivates the filter
Regardless of whether a filter has been activated or not, the event is signalled as
completed as we have now deaklt with it (only checked for a filter if a pattern was not
associated.
RETURNS
void
*/
void LedsCheckForFilter ( LedTaskData * pLEDTask , headsetEvents_t pEvent )
{
uint16 lFilterIndex = 0 ;
for (lFilterIndex = 0 ; lFilterIndex < pLEDTask->gLMNumFiltersUsed ; lFilterIndex ++ )
{
if ( pLEDTask->gEventFilters[ lFilterIndex ].Event == pEvent )
{
if (pLEDTask->gEventFilters[ lFilterIndex ].IsFilterActive )
{
LedsEnableFilter (pLEDTask , lFilterIndex , TRUE) ;
/* If it is an overide fLED filter and the currently playing pattern is OFF then turn on the overide led immediately*/
if ( pLEDTask->gEventFilters [ lFilterIndex].OverideLEDActive )
{
uint16 lOverideLEDIndex = pLEDTask->gEventFilters[ lFilterIndex].OverideLED ;
/* this should only happen if the led in question is currently off*/
if ( pLEDTask->gActiveLEDS[lOverideLEDIndex].OnOrOff == LED_OFF)
{
PioSetLedPin ( pLEDTask , lOverideLEDIndex , LED_ON) ;
}
}
}
else
{
uint16 lFilterToCancel = pLEDTask->gEventFilters[ lFilterIndex ].FilterToCancel ;
/*disable the according filter*/
if ( lFilterToCancel != 0 )
{
uint16 lFilterToCancelIndex = lFilterToCancel - 1 ;
uint16 lOverideLEDIndex = pLEDTask->gEventFilters[ lFilterToCancelIndex ].OverideLED ;
LED_DEBUG(("LED: FilCancel[%d][%d] [%d]\n",lFilterIndex + 1 , lFilterToCancel , lFilterToCancelIndex )) ;
/*lFilter To cancel = 1-n, LedsEbnable filter requires 0-n */
LedsEnableFilter (pLEDTask , lFilterToCancelIndex , FALSE ) ;
if ( pLEDTask->gActiveLEDS[lOverideLEDIndex].OnOrOff == LED_OFF)
{
/* LedsHandleOverideLED ( pLEDTask , LED_OFF) ;*/
if ( pLEDTask->gEventFilters [ lFilterToCancelIndex].OverideLEDActive )
{
PioSetLedPin ( pLEDTask , pLEDTask->gEventFilters[lFilterToCancelIndex].OverideLED , LED_OFF) ;
}
}
}
else
{
LED_DEBUG(("LED: Fil !\n")) ;
}
}
LED_DEBUG(("LM : Filter Found[%d]A[%x] [%d]\n", lFilterIndex , pEvent , pLEDTask->gEventFilters[ lFilterIndex ].IsFilterActive )) ;
}
}
/*there was no pattern event configured
indicate that we have dealt with the event and there was no pattern associated */
/* LedsSendEventComplete ( pEvent , FALSE) ;*/
}
/****************************************************************************
NAME
LEDManagerIndicateState
DESCRIPTION
This function kicks off a state indication. It cancels any previous state
indication but does not overide an event indication.
RETURNS
void
*/
void LedsIndicateState ( LedTaskData * pLEDTask , headsetState pState )
{
uint16 lPrimaryLED = 0;
uint16 lSecondaryLED = 0 ;
LEDPattern_t * lPattern = pLEDTask->gStatePatterns[pState] ;
LMPrintPattern( lPattern ) ;
lPrimaryLED = lPattern->LED_A;
lSecondaryLED = lPattern->LED_B;
LED_DEBUG(("LED: st[%x][%x]", pLEDTask->gActiveLEDS[lPrimaryLED].Type , pLEDTask->gActiveLEDS[lSecondaryLED].Type)) ;
/*only indicate state if both leds we want to use are not currently indicating an event*/
if ( ( pLEDTask->gActiveLEDS[lPrimaryLED].Type != IT_EventIndication )
&& ( pLEDTask->gActiveLEDS[lSecondaryLED].Type != IT_EventIndication ) )
{
LED_DEBUG(("LED: IS : OK\n")) ;
/*Find the LEDS that are set to indicate states and Cancel the messages,
-do not want to indicate more than one state at a time*/
LedsCancelStateIndications ( pLEDTask ) ;
/*Set up the Active LED with the State we want to indicate*/
LedsSetLedActivity ( &pLEDTask->gActiveLEDS[lPrimaryLED] , IT_StateIndication , pState ) ;
/*Set the Alternative LED up with the same info*/
LedsSetLedActivity ( &pLEDTask->gActiveLEDS[lSecondaryLED] , IT_StateIndication , pState ) ;
/* - need to set the LEDS to a known state before starting the pattern*/
LedsTurnOffLEDPair ( pLEDTask , lPattern , TRUE ) ;
LED_DEBUG(("LED: st2[%x][%x]", pLEDTask->gActiveLEDS[lPrimaryLED].Type , pLEDTask->gActiveLEDS[lSecondaryLED].Type)) ;
/*Handle permanent output leds*/
if ( lPattern->NumFlashes == 0 )
{
/*set the pins on or off as required*/
if ( lPattern->OnTime > 0 )
{
LED_DEBUG(("LM :ST PIO_ON\n")) ;
LedsTurnOnLEDPair ( pLEDTask ,lPattern , &pLEDTask->gActiveLEDS[lPrimaryLED] ) ;
}
else if ( lPattern->OffTime > 0 )
{
LED_DEBUG(("LM :ST PIO_OFF\n")) ;
LedsTurnOffLEDPair ( pLEDTask , lPattern ,TRUE) ;
}
}
else
/*send the first message for this state LED indication*/
MessageSendLater (&pLEDTask->task , lPrimaryLED , 0 , LEDS_STATE_START_DELAY_MS ) ;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -