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

📄 av_headset_controls.c

📁 CSR蓝牙芯片 无线蓝牙耳机的语音网关程序 蓝牙耳机程序已经上传
💻 C
字号:
/****************************************************************************
Copyright (C) Cambridge Silicon Radio Ltd. 2004

FILE NAME
    av_headset_controls.c        

DESCRIPTION
    
NOTES

*/


/****************************************************************************
    Header files
*/
#include "headset_private.h"

#include "av_headset_controls.h"
#include "av_headset_kalimba.h"

#include "hfp_headset_slc.h"
#include "cvc_headset.h"

#include <stdlib.h>
#include <string.h>
#include <panic.h>
#include <pio.h>
#include <ps.h>
#include <codec.h>
#include <pcm.h>


static void controls_handler(Task task, MessageId id, Message message);


static const uint8 vgsToCodecGain[16] = {0, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 17, 19};


/* 
    Send remote control command to remote device 
*/
static void sendAVRCP(headsetTaskData* app, avc_operation_id op_id, uint8 state)
{
    app->avrcp_pending = TRUE;
    
    /* Send a key press */
    AvrcpPassthrough(app->avrcp,
                      subunit_panel,  
                      0,
                      state,
                      op_id,
                      0,
                      0);   

}

/*************************************************************************
NAME    
     avHeadsetInitialiseControls
    
DESCRIPTION
     Initialises power and button control
RETURNS
     
*/
void avHeadsetInitialiseControls(headsetTaskData* app)
{
    /* hold power on so user can release the button */
    PioSet(POWER_HOLD,POWER_HOLD);
    PioSetDir(POWER_HOLD,POWER_HOLD);

    /* Read the volume from PS. The volume is stored as:
       
          HF Volume     |    AV volume  
       ---------------------------------
       |15| | | | | | |8|7| | | | | | |0|
       ---------------------------------
                       
    */
    if (!PsRetrieve(VOLUME_LEVEL, &app->speaker_volume, sizeof(app->speaker_volume)))
        /* set the headset gain to a reasonable value */
        app->speaker_volume = 10 | (10 << VOLUME_SHIFT);
	DEBUG(("avHeadsetInitialiseControls()\n"));

    /* initial the handler task */
    app->controls_task.handler = controls_handler;
}

/*************************************************************************
NAME    
     avHeadsetStartPowerDown
    
DESCRIPTION
     Start to power down the headset gracefully
     
RETURNS
     
*/
void avHeadsetStartPowerDown(headsetTaskData* app)
{
	if (app->powering_down)
		return;
	
    app->powering_down = TRUE;
    
    /* Close down any active AV link */
    if ((app->a2dp_state == avHeadsetA2dpConnected) || (app->a2dp_state == avHeadsetA2dpStreaming))
    {
        app->a2dp_state = avHeadsetA2dpConnected;
        A2dpClose(app->a2dp, app->media_sink);
    }
    /* Close down any active AVRCP link */
    if (app->avrcp_state == avHeadsetAvrcpConnected)
    {
        avHeadsetSetAvrcpState(avHeadsetAvrcpDisconnecting);
        AvrcpDisconnect(app->avrcp);
    }
    /* Close down any active AG link */
    if ((app->hfp_state != headsetInitialising) && (app->hfp_state != headsetReady))
        hfpHeadsetDisconnectSlc(app);
    
    MessageSendLater(getAppTask(), APP_POWER_OFF_IND, 0, (uint32) 5000);
    
    avHeadsetCheckPowerDownStatus(app);
        
}

/*************************************************************************
NAME    
     avHeadsetCheckPowerDownStatus
    
DESCRIPTION
     Checks if connections have been successfully dropped and we have
     initiated power down. We can then power off.
     
RETURNS
     
*/
void avHeadsetCheckPowerDownStatus(const headsetTaskData *app)
{
    if (!app->powering_down)
        return;
    
    if ((app->a2dp_state == avHeadsetA2dpReady) && (app->avrcp_state == avHeadsetAvrcpReady) && (app->hfp_state == headsetReady))
    {
        DEBUG(("OK! We can power down early\n"));

        (void) MessageCancelAll(getAppTask(), APP_POWER_OFF_IND);
        MessageSend(getAppTask(), APP_POWER_OFF_IND, 0);
    }
}

/*************************************************************************
NAME    
     avHeadsetPowerDown
    
DESCRIPTION
     Power down the headset
     
RETURNS
     
*/
void avHeadsetPowerDown(const headsetTaskData *app)
{
    DEBUG(("PowerDown and Panic\n"));
 
    /* Power down the codec */
    CodecPowerDown(app->codec_task);

    /* Store the current volume */
    (void) PsStore(VOLUME_LEVEL, &app->speaker_volume, sizeof(app->speaker_volume));

    /* disable power hold and LED */
    PioSetDir(POWER_HOLD | LED, 0);
    PioSet(POWER_HOLD | LED,0);

    /* in case the interface board is attached
       and keeping us alive we also halt the program. */
    Panic();
}


/*************************************************************************
NAME    
     avHeadsetHandleAvVolUp
    
DESCRIPTION
     Increase AV volume in single step increments
     
RETURNS
     
*/
void avHeadsetHandleAvVolUp(headsetTaskData* app)
{
    if ((app->speaker_volume & 0xFF) < 15)
        app->speaker_volume++;
#ifdef INCLUDE_CVC
	if (app->active_profile== hfp_active)
	{
		CvcHeadsetGainRequest(app->speaker_volume);
		DEBUG(("clarity on speaker gain request VolUp=%d\n",app->speaker_volume));
	}
	else if (app->active_profile== av_active)
#endif
	{
	    avHeadsetUpdateAvVolume(app->codec_task, app->speaker_volume);
		DEBUG(("avHeadsetUpdate volume for a2dp VolUp=%d\n",app->speaker_volume));
	}
}


/*************************************************************************
NAME    
     avHeadsetHandleAvVolDown
    
DESCRIPTION
     Decrease AV volume in single step increments
     
RETURNS
     
*/
void avHeadsetHandleAvVolDown(headsetTaskData* app)
{
    if ((app->speaker_volume & 0xFF) > 0)
        app->speaker_volume--;
	
#ifdef INCLUDE_CVC
	if (app->active_profile== hfp_active)
	{
		CvcHeadsetGainRequest(app->speaker_volume);
		DEBUG(("clarity on speaker gain request VolDown=%d\n",app->speaker_volume));
	}
	else if (app->active_profile== av_active)
#endif
	{
        avHeadsetUpdateAvVolume(app->codec_task, app->speaker_volume);
		DEBUG(("avHeadsetUpdate volume for a2dp VolDown=%d\n",app->speaker_volume));
	}
}


/*************************************************************************
NAME    
     avHeadsetHandleHfVolUp
    
DESCRIPTION
     Increase Hands free volume in single step increments
     
RETURNS
     
*/
void avHeadsetHandleHfVolUp(headsetTaskData* app)
{
    uint16 ag_volume = app->speaker_volume >> VOLUME_SHIFT;
    if (ag_volume < 15)
        ag_volume++;
    app->speaker_volume = (app->speaker_volume & 0xFF) | (ag_volume << VOLUME_SHIFT);
#ifdef INCLUDE_CVC
	CvcHeadsetVolume(app->speaker_volume);
#else
	avHeadsetUpdateHfVolume(app->codec_task, app->speaker_volume);
#endif
}


/*************************************************************************
NAME    
     avHeadsetHandleHfVolDown
    
DESCRIPTION
     Decrease Hands free volume in single step increments
     
RETURNS
     
*/
void avHeadsetHandleHfVolDown(headsetTaskData* app)
{
    uint16 ag_volume = app->speaker_volume >> VOLUME_SHIFT;
    if (ag_volume > 0)
        ag_volume--;
    app->speaker_volume = (app->speaker_volume & 0xFF) | (ag_volume << VOLUME_SHIFT);
#ifdef INCLUDE_CVC
	CvcHeadsetVolume(app->speaker_volume);
#else
    avHeadsetUpdateHfVolume(app->codec_task, app->speaker_volume);
#endif
}


/*************************************************************************
NAME    
     avHeadsetUpdateAvVolume
    
DESCRIPTION
     Set the codec gain to an absolute value
     
RETURNS
     
*/
void avHeadsetUpdateAvVolume(Task codec_task, uint16 gain)
{
    gain &= 0xFF; 
    if (gain <= 15)
        CodecSetOutputGain(codec_task, vgsToCodecGain[gain], left_and_right_ch);
    DEBUG(("AV volume: %d\n",gain));
}


/*************************************************************************
NAME    
     avHeadsetUpdateHfVolume
    
DESCRIPTION
     Set the codec gain to an absolute value
     
RETURNS
     
*/
void avHeadsetUpdateHfVolume(Task codec_task, uint16 gain)
{
    gain = gain >> VOLUME_SHIFT; 
    if (gain <= 15)
        CodecSetOutputGain(codec_task, vgsToCodecGain[gain], left_and_right_ch);
    DEBUG(("HF volume: %d\n",gain));
}


enum
{
    PAUSE_PRESS,
    PAUSE_RELEASE,
    PLAY_PRESS,
    PLAY_RELEASE,
    FORWARD_PRESS,
    FORWARD_RELEASE,
    BACKWARD_PRESS,
    BACKWARD_RELEASE,
    STOP_PRESS,
    STOP_RELEASE
};

/*************************************************************************
NAME    
     controls_handler
    
DESCRIPTION
     Called when a button state change is pending which can now be sent.

     Messages will only be delivered when avrcp_pending is FALSE and
     hence when we are clear to send the message.
     
RETURNS
     
*/
static void controls_handler(Task task, MessageId id, Message message)
{
	task = task;
	message = message;

    switch (id)
    {
        case PAUSE_PRESS:
            DEBUG(("Sending Pause Pressed\n"));
            sendAVRCP(getApp(), opid_pause, 0);
            break;

        case PAUSE_RELEASE:
            DEBUG(("Sending Pause Released\n"));
            sendAVRCP(getApp(), opid_pause, 1);
            break;

        case PLAY_PRESS:
            DEBUG(("Sending Play Pressed\n"));
            sendAVRCP(getApp(), opid_play, 0);
            break;

        case PLAY_RELEASE:
            DEBUG(("Sending Play Released\n"));
            sendAVRCP(getApp(), opid_play, 1);
            break;

        case FORWARD_PRESS:
            DEBUG(("Sending Forward Pressed\n"));
            sendAVRCP(getApp(), opid_forward, 0);
            break;

        case FORWARD_RELEASE:
            DEBUG(("Sending Forward Released\n"));
            sendAVRCP(getApp(), opid_forward, 1);
            break;

        case BACKWARD_PRESS:
            DEBUG(("Sending Backward Pressed\n"));
            sendAVRCP(getApp(), opid_backward, 0);
            break;

        case BACKWARD_RELEASE:
            DEBUG(("Sending Backward Released\n"));
            sendAVRCP(getApp(), opid_backward, 1);
            break;

        case STOP_PRESS:
            DEBUG(("Sending Stop Pressed\n"));
            sendAVRCP(getApp(), opid_stop, 0);
            break;

        case STOP_RELEASE:
            DEBUG(("Sending Stop Released\n"));
            sendAVRCP(getApp(), opid_stop, 1);
            break;

		default:
			break;
    }
}


/*************************************************************************
NAME    
     avHeadsetPausePress
    
DESCRIPTION
     Signal that pause has been pressed.
     Note that the AV Control specification states that the pause
     button will toggle between playing/paused.
     
RETURNS
     
*/
void avHeadsetPausePress(headsetTaskData* app)
{
    /* see controls_handler description */
    MessageSendConditionally(&app->controls_task, PAUSE_PRESS, NULL, &app->avrcp_pending);
}

/*************************************************************************
NAME    
     avHeadsetPauseRelease
    
DESCRIPTION
     Signal that pause has been released
     
RETURNS
     
*/
void avHeadsetPauseRelease(headsetTaskData* app)
{
    /* see button_handler message queue description */
    MessageSendConditionally(&app->controls_task, PAUSE_RELEASE, NULL, &app->avrcp_pending);
}

/*************************************************************************
NAME    
     avHeadsetPlayPress
    
DESCRIPTION
     Signal that play has been pressed
     
RETURNS
     
*/
void avHeadsetPlayPress(headsetTaskData* app)
{
    /* see controls_handler description */
    MessageSendConditionally(&app->controls_task, PLAY_PRESS, NULL, &app->avrcp_pending);
}

/*************************************************************************
NAME    
     avHeadsetPlayRelease
    
DESCRIPTION
     Signal that play has been released
     
RETURNS
     
*/
void avHeadsetPlayRelease(headsetTaskData* app)
{
    /* see button_handler message queue description */
    MessageSendConditionally(&app->controls_task, PLAY_RELEASE, NULL, &app->avrcp_pending);
}


/*************************************************************************
NAME    
     avHeadsetForwardPress
    
DESCRIPTION
     Signal that Forward has been pressed
     
RETURNS
     
*/
void avHeadsetForwardPress(headsetTaskData* app)
{
    /* see controls_handler description */
    MessageSendConditionally(&app->controls_task, FORWARD_PRESS, NULL, &app->avrcp_pending);
}

/*************************************************************************
NAME    
     avHeadsetForwardRelease
    
DESCRIPTION
     Signal that Forward has been released
     
RETURNS
     
*/
void avHeadsetForwardRelease(headsetTaskData* app)
{
    /* see button_handler message queue description */
    MessageSendConditionally(&app->controls_task, FORWARD_RELEASE, NULL, &app->avrcp_pending);
}

/*************************************************************************
NAME    
     avHeadsetBackwardPress
    
DESCRIPTION
     Signal that Backward has been pressed
     
RETURNS
     
*/
void avHeadsetBackwardPress(headsetTaskData* app)
{
    /* see controls_handler description */
    MessageSendConditionally(&app->controls_task, BACKWARD_PRESS, NULL, &app->avrcp_pending);
}

/*************************************************************************
NAME    
     avHeadsetBackwardRelease
    
DESCRIPTION
     Signal that Backward has been released
     
RETURNS
     
*/
void avHeadsetBackwardRelease(headsetTaskData* app)
{
    /* see button_handler message queue description */
    MessageSendConditionally(&app->controls_task, BACKWARD_RELEASE, NULL, &app->avrcp_pending);
}

/*************************************************************************
NAME    
     avHeadsetStopPress
    
DESCRIPTION
     Signal that Stop has been pressed
     
RETURNS
     
*/
void avHeadsetStopPress(headsetTaskData* app)
{
    /* see controls_handler description */
    MessageSendConditionally(&app->controls_task, STOP_PRESS, NULL, &app->avrcp_pending);
}

/*************************************************************************
NAME    
     avHeadsetStopRelease
    
DESCRIPTION
     Signal that Stop has been released
     
RETURNS
     
*/
void avHeadsetStopRelease(headsetTaskData* app)
{
    /* see button_handler message queue description */
    MessageSendConditionally(&app->controls_task, STOP_RELEASE, NULL, &app->avrcp_pending);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -