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

📄 cvc_headset.c

📁 针对bluelab3.42的handsfree车载蓝牙的参考
💻 C
字号:
/****************************************************************************
Copyright (C) Cambridge Silicon Radio Ltd. 2004-2006
Part of BlueLab 3.4.2-release

FILE NAME
	cvc_headset.c        

DESCRIPTION
    Support for CVC in av_headset_hfp
	
	Only active if INCLUDE_CVC is defined in the project properties.
	
NOTES
	The supporting DSP code is supplied as a preassembled .kap file and is
	time limited until licenced.
*/

#ifdef INCLUDE_CVC

/****************************************************************************
	Header files
*/

#include "headset_private.h"
#include "headset_tones.h"
#include "headset_volume.h"
#include "cvc_headset.h"
#include "cvcdsp.h"


#include <codec.h>
#include <file.h>
#include <kalimba.h>
#include <kalimba_standard_messages.h>
#include <pcm.h>
#include <stdlib.h>
#include <string.h>
#include <transform.h>
#include <panic.h>
#include <ps.h>
#include <pio.h>
#include <message.h>
#include <stream.h>


#ifdef DEBUG_CVC
#define CVC_DEBUG(x) DEBUG(x)
#else
#define CVC_DEBUG(x) 
#endif


/* CVC Message IDs */
#define CVC_READY				0x1000
#define CVC_SETMODE				0x1001
#define CVC_VOLUME				0x1002

#define CVC_CODEC				0x1006
#define CVC_STATUS		        0x1007

#define CVC_KEY_CMD				0x100A
#define CVC_KEY_RESP			0x100B

/* System Modes */
#define SYSMODE_HFK			1
#define SYSMODE_ASR			2
#define SYSMODE_PSTHRGH		3

/* Call State */
#define CALLST_CONNECTED	1
#define CALLST_MUTE         3


static unsigned short CvcKey[4];

/*	Filename containing the CHF DSP code.	*/
static const char enc_codec[] = "cvc/cvc.kap";

static bool cvc_init(headsetTaskData* app);
static void start_kalimba(headsetTaskData* app);
static void connect_streams(headsetTaskData *app);
static void dsp_handler(Task, MessageId, Message);


static bool cvc_init(headsetTaskData* app)
{
    bool ret = FALSE;
    
    if (!app->cvc.hfkdspready)
    {
        start_kalimba(app);
            
        /* Disconnect anything already connected to PCM slots 0 and 1 */
        StreamDisconnect(StreamPcmSource(0), StreamPcmSink(0));
        StreamDisconnect(StreamPcmSource(1), StreamPcmSink(1));
    
        /*
            Set both ports to none to allow reassigning of internal DACs below.
            (A DAC can only be routed to one port at a time!)
        */
        (void) PanicFalse(PcmClearRouting(0));
        (void) PanicFalse(PcmClearRouting(1));
   
        /* Configure port 0 to be routed to internal codec A and B, with a sample rate of 8k. */
        (void) PanicFalse(PcmRateAndRoute(0, PCM_NO_SYNC, (uint32) 8000, (uint32) 8000, VM_PCM_INTERNAL_A_AND_B));
        ret = TRUE;        
    }
   
    return ret;
}

   /* The following function is used to start the DSP code.  The code   */
   /* for the DSP resides in the constant data area as a file in a file */
   /* system.  Once the file is located, the file is loaded into the DSP*/
   /* and started.                                                      */

static void start_kalimba(headsetTaskData* app)
{
    /* Find the codec file in the file system                            */
    FILE_INDEX index = FileFind(FILE_ROOT,enc_codec,sizeof(enc_codec)-1/*don't pass terminator*/);

    if(index == FILE_NONE)
    {
        /* Error - can't find file        */
        CVC_DEBUG(("CVC: CHF file index = %x \n",index));
	   Panic();
    }
    
    (void) MessageCancelAll(&app->cvc.task, MESSAGE_FROM_KALIMBA);
    MessageKalimbaTask(&app->cvc.task);
   
    /* Load the cvc algorithm into Kalimba                                       */
    if(!KalimbaLoad(index))
    {
        CVC_DEBUG(("CVC: Kalimba load fail\n"));
        Panic();
    }
   
    /* Now the kap file has been loaded, wait for the CVC_READY message from the
      dsp to be sent to the dsp_handler function. */  
}

static void connect_streams(headsetTaskData *app)
{
    bool r1, r2, r3, r4;

    /* Connect the stream from the Mic to the DSP and the stream 
       from the DSP to the Speaker. */
    r1 = StreamConnect(StreamPcmSource(0),StreamKalimbaSink(0));
    r2 = StreamConnect(StreamKalimbaSource(0),StreamPcmSink(0));
    
	/* Plug Incoming SCO link into DSP Channel 1 Input.                   */
	r3 = StreamConnect(StreamSourceFromSink(app->sco_sink),StreamKalimbaSink(1));
	/* Plug DSP Channel 1 Output into Outoing SCO Link */
	r4 = StreamConnect(StreamKalimbaSource(1),app->sco_sink);
    
    CVC_DEBUG(("CVC: connect_streams %d %d %d %d\n",r1,r2,r3,r4));
    
    CodecSetOutputGainNow(app->codec_task, app->cvc.cvc_output_codec_gain, left_and_right_ch);
    CvcHeadsetVolume(app);
    
    /* Set the Dsp mode */
    CvcSetMode(app);
}

   /* The following function is used to handle messages that are        */
   /* dispatched from the DSP.                                          */

typedef struct
{
    uint16 id;
    uint16 a;
    uint16 b;
    uint16 c;
    uint16 d;
} DSP_REGISTER_T;

static void dsp_handler(Task task, MessageId id, Message message) 
{
	if (id== MESSAGE_FROM_KALIMBA)
	{
		const DSP_REGISTER_T *m = (const DSP_REGISTER_T *) message;
		uint16 a      = m->a;
		uint16 b      = m->b;
        
        headsetTaskData *app = getApp();

		CVC_DEBUG(("CVC: dsp_handler dsp_id = %x a= %x b= %x c= %x d= %x\n" ,m->id,a,b,m->c,m->d));
	
		switch (m->id) 
		 {
         case CVC_READY:
            /* This command is set to us to indicate that the DSP is    */
            /* initialized and ready.  At this point we need to send the*/
            /* configuration parameters to the DSP.  Allocate memory to */
            /* hold a configuration record.                             */
			a = CvcConfigureDsp(PS_PARAM_BASE,NULL,0);
            CVC_DEBUG(("CVC: CVC_READY: DSP is initialized and ready (%x)\n",a));
            
            /* DSP is up and running */
   			app->cvc.hfkdspready = 1;

            if (app->sco_sink && (app->pcm_audio_state == pcm_sco))
            {
                CVC_DEBUG(("CVC: Ok to connect streams\n"));
    			connect_streams(app);
            }
			
            break;
			
		case CVC_CODEC:
            /* We have received a message that defines the values that  */
            /* are to be loaded for gain levels.  Parameter 1 (a)       */
            /* defines the DAC (speaker) gain.  Parameter 2 (b) defines */
            /* the ADC (microphone gain).  These levels are meant to be */
            /* fixed throughout CVC operation.  Volume button pushes    */
            /* do not change codec gain values.  Instead, the CVC       */
            /* algorithm handles these.                                 */
 
            app->cvc.cvc_output_codec_gain = a;
            app->cvc.cvc_input_codec_gain = b;
   			CodecSetOutputGainNow(app->codec_task, a, left_and_right_ch);
            CVC_DEBUG(("CVC: CVC_CODEC: Input gain = 0x%x  Output gain = 0x%x\n",b,a));
            if((b & 0x8000)  == 0x8000)
			{
				CodecEnableMicInputGainA(1);
				CodecEnableMicInputGainB(1);
			}
			else
			{
				CodecEnableMicInputGainA(0);
				CodecEnableMicInputGainB(0);
			}
            CodecSetInputGainNow(app->codec_task, b, left_and_right_ch);
            break;
			
		case CVC_KEY_CMD:
			
			b = CvcSecurityCheck(CvcKey,a);
			CVC_DEBUG(("CVC: CVC_KEY_CMD: %x %x\n",a,b));
			break;
      }
	}
}

void CvcInitialise(headsetTaskData *app)
{
    app->cvc.task.handler = dsp_handler;    
    app->cvc.cvc_output_codec_gain = 0;
    app->cvc.cvc_input_codec_gain = 0;
    
    /* Check for Security */
	PsRetrieve(PS_SEC_KEY,CvcKey, sizeof(uint16)*4);
}

void CvcHeadsetConnect(headsetTaskData *app)
{
	CVC_DEBUG(("CVC: hfkdspready = %x\n",app->cvc.hfkdspready));
	CVC_DEBUG(("CVC: hfp_state = %x\n",app->hfp_state));
	if (!cvc_init(app))
    {
        /* Disconnect anything already connected to PCM slots 0 and 1 */
        StreamDisconnect(0, StreamPcmSink(0));
        /* Now connect up the new streams */
    	connect_streams(app);
        CVC_DEBUG(("CVC: Cvc sco connected\n"));
    }
}

void CvcHeadsetUnloaded(headsetTaskData *app)
{
    /* The DSP has been reloaded by some other part of the application */
    app->cvc.hfkdspready = 0;
    CVC_DEBUG(("CVC: Cvc unloaded\n"));
}

void CvcHeadsetVolume(headsetTaskData *app)
{
    uint16 gain = app->speaker_volume.hfp_volume;
	if(app->cvc.hfkdspready)
    {
       CVC_DEBUG(("CVC: Cvc volume = %x\n",gain));
	   if(!KalimbaSendMessage(CVC_VOLUME, gain, 0 ,0, 0))
	   {
		  CVC_DEBUG(("CVC: SetVolume FAILURE\n"));
	   }
   }
}

void CvcSetMode(headsetTaskData *app)
{
    if (!app->cvc.hfkdspready)
        return;
    
    if (app->voice.voice_recognition_enabled)
    {
        CVC_DEBUG(("CVC: SetMode SYSMODE_ASR\n"));
        /* Set the DSP mode to apply noise reduction only. */
        if(!KalimbaSendMessage(CVC_SETMODE, SYSMODE_ASR, 0, 0, 0))
        {
		    CVC_DEBUG(("CVC: SetMode SYSMODE_ASR FAILURE\n"));
        }
    }
    else
    { 
        CVC_DEBUG(("CVC: Set mode SYSMODE_HFK "));
        if (app->mic_mute_on)
        {
            CVC_DEBUG(("(CALLST_MUTE)\n"));
            if (!KalimbaSendMessage(CVC_SETMODE, SYSMODE_HFK, 0, CALLST_MUTE, 0))
            {
                CVC_DEBUG(("CVC: Set Mode SYSMODE_HFK (CALLST_MUTE) FAILURE\n"));
            }
        }
        else
        {   
            CVC_DEBUG(("(CALLST_CONNECTED)\n"));
            /* Set the DSP mode to apply echo cancellation and noise reduction. */
            if(!KalimbaSendMessage(CVC_SETMODE, SYSMODE_HFK, 0, CALLST_CONNECTED, 0))
            {
		        CVC_DEBUG(("CVC: SetMode SYSMODE_HFK (CALLST_CONNECTED) FAILURE\n"));
            }
        }
    }
}

#else /* ifndef INCLUDE_CVC */

extern int cvc_headset_dummy_int; /* Suppress empty-file error */

#endif

⌨️ 快捷键说明

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