我正在将CSR8675蓝牙芯片与ADK4.0.1(音频开发套件;用于编程CSR音频芯片的软件)
(该芯片将用于与使用蓝牙的其他设备进行连接,但这不是蓝牙的特殊问题)
CSR的示例程序演示了如何在音频源和接收器之间进行直接连接,但是我想进行间接连接(以更好地理解从源到接收器复制音频数据时所涉及的缓冲区的大小和组织)
这是我对其示例代码进行的修改:
/*
Copyright (c) 2006 - 2015 Qualcomm Technologies International, Ltd.
An example app for routing audio through the Kalimba DSP from ADC to DAC
*/
#include <kalimba.h>
#include <kalimba_standard_messages.h>
#include <file.h>
#include <string.h>
#include <panic.h>
#include <source.h>
#include <sink.h>
#include <stream.h>
#include <connection.h>
#include <micbias.h>
#include <pio.h>
#include <stdio.h>
#include <transform.h>
void PioSetPio (uint16 pPIO , bool pOnOrOff);
/* Select Amp PIO depending on board used. If not defined, assume the CNS10001v4 board is assumed. */
#ifdef H13179V2
#define POWER_AMP_PIO 14
#else /* Assume CNS10001v4 */
#define POWER_AMP_PIO 4
#endif
/* Define the macro "BYPASS_KALIMBA" to bypass Kalimba DSP otherwise direct ADC->DAC */
/* #define BYPASS_KALIMBA */
/* Define the macro "MIC_INPUT" for microphone input otherwise line-in input */
#define MIC_INPUT
/* Location of DSP kap file in the file system */
static const char kal[] = "my_first_dsp_app_kalimba/my_first_dsp_app_kalimba.kap";
uint16 sampleRate = 48000;
void start_kalimba(void);
/* void connect_streams(void); */
static TaskData aud_data_inp;
void aud_inp_handler(Task task, MessageId id, Message message);
Source audSrc_L;
Sink audSink_L;
uint16 offset_aud_inp;
uint8* dest_aud_inp;
uint16 length_aud_inp;
uint16 srcSize;
const uint8* audSrcData_L;
uint16 length;
#define ENABLE_MAIN_C_PRINTFx
#ifdef ENABLE_MAIN_C_PRINTF
#define MAIN_C_MYPRINTF(x) printf x
#else
#define MAIN_C_MYPRINTF(x) /* */
#endif
Transform t1, t2, t3;
/* Main VM routine */
int main(void)
{
/* Load the Kalimba */
/* start_kalimba(); */
aud_data_inp.handler = aud_inp_handler;
audSrc_L = StreamAudioSource( AUDIO_HARDWARE_CODEC, AUDIO_INSTANCE_0, AUDIO_CHANNEL_A ); /* ORIGINAL */
PanicNull(audSrc_L);
PanicFalse( SourceConfigure(audSrc_L, STREAM_CODEC_INPUT_RATE, sampleRate) );
PanicFalse( SourceConfigure(audSrc_L, STREAM_CODEC_MIC_INPUT_GAIN_ENABLE, 1) ); /* ORIGINALLY USED: 1 */
PanicFalse(MicbiasConfigure(MIC_BIAS_0, MIC_BIAS_ENABLE, MIC_BIAS_FORCE_ON));
PanicFalse( SourceConfigure(audSrc_L, STREAM_CODEC_INPUT_GAIN, 10) ); /* ORIGINALLY USED: 10 */
PioSetPio(POWER_AMP_PIO, TRUE);
audSink_L = StreamAudioSink( AUDIO_HARDWARE_CODEC, AUDIO_INSTANCE_0, AUDIO_CHANNEL_A ); /* ORIGINAL */
PanicNull(audSink_L);
PanicFalse( SinkConfigure(audSink_L, STREAM_CODEC_OUTPUT_RATE, sampleRate) );
PanicFalse( SinkConfigure(audSink_L, STREAM_CODEC_OUTPUT_GAIN, 15) ); /* ORIGINALLY USED: 15 */
#if 1
/* BLOCK (1) */
/* printf("Transconf res = 0x%x\n", TransformConfigure(t1, VM_TRANSFORM_CHUNK_CHUNK_SIZE, 1) ); */
t1 = TransformChunk(audSrc_L, audSink_L);
/* printf("t1 = 0x%x\n", (unsigned int)t1 ); */
TransformConfigure(t1, VM_TRANSFORM_CHUNK_CHUNK_SIZE, 1);
/* printf("Transconf res = 0x%x\n", TransformConfigure(t1, VM_TRANSFORM_CHUNK_CHUNK_SIZE, 1) ); */
TransformStart( t1 );
MessageSinkTask(audSink_L, &aud_data_inp);
MessageSinkTask(StreamSinkFromSource(audSrc_L), &aud_data_inp);
#endif
/* PanicFalse( StreamConnect(audSrc_L, audSink_L) ); */
/* Connect up the ADCs and DACS */
/* connect_streams(); */
/* Start the Kalimba */
/* PanicFalse( KalimbaSendMessage(KALIMBA_MSG_GO,0,0,0,0) ); */
/* Remain in MessageLoop (handles messages) */
MessageLoop();
return 0;
}
void start_kalimba(void)
{
/* Find the codec file in the file system */
FILE_INDEX index = FileFind( FILE_ROOT, (const char *)kal, strlen(kal) );
/* Did we find the desired file? */
PanicFalse( index != FILE_NONE );
/* Load the codec into Kalimba */
PanicFalse( KalimbaLoad( index ) );
}
void PioSetPio (uint16 pPIO , bool pOnOrOff)
{
uint16 lPinVals = 0 ;
uint16 lWhichPin = (1<< pPIO) ;
if ( pOnOrOff )
{
lPinVals = lWhichPin ;
}
else
{
lPinVals = 0x0000;/*clr the corresponding bit*/
}
/*(mask,bits) setting bit to a '1' sets the corresponding port as an output*/
PioSetDir32( lWhichPin , lWhichPin );
/*set the value of the pin*/
PioSet32 ( lWhichPin , lPinVals ) ;
}
#if 1
/* original app handler */
void aud_inp_handler(Task task, MessageId id, Message message){
task = task;
MAIN_C_MYPRINTF(("\nENTERED aud_inp_handler() HANDLER\n"));
switch(id){
case MESSAGE_MORE_DATA:
MAIN_C_MYPRINTF(("Received MESSAGE_MORE_DATA Message in aud_inp_handler()\n"));
srcSize = SourceSize( audSrc_L );
MAIN_C_MYPRINTF(("srcSize = %d ( aud_inp_handler() )\n", srcSize));
audSrcData_L = SourceMap(audSrc_L);
if( srcSize == 0 || srcSize < 128) break; /* srcSize == 0 -> invalid source */
else if( srcSize == 128){
MAIN_C_MYPRINTF(("Inside else if( srcSize == 64){\n" ));
length = srcSize;
offset_aud_inp = SinkClaim(audSink_L, length);
if(offset_aud_inp == 0xFFFF) Panic(); /* Space not available; this is a memory error, should not happen */
/* Map the sink into memory space */
dest_aud_inp = SinkMap(audSink_L);
(void) PanicNull(dest_aud_inp);
/* Copy the string into the claimed space */
memcpy(dest_aud_inp+offset_aud_inp, audSrcData_L, length);
/* Flush the data out to the uart */
PanicZero(SinkFlush(audSink_L, length)); /* L_Src -> kalSink(0) */
/* Source can be dropped after sending all the data in source to the sink */
SourceDrop(audSrc_L, srcSize);
}
break;
case MESSAGE_MORE_SPACE:
break;
default:
MAIN_C_MYPRINTF(("Ignored Message in aud_inp_handler()\n"));
break;
}
}
#endif
我尝试在
/* BLOCK (1) */
上启用和禁用代码块,结果相同如果我通过启用
/* PanicFalse( StreamConnect(audSrc_L, audSink_L) ); */
线启用直接连接,则au从源到接收器的dio路由没有任何问题在这种情况下,如何设置源和接收器的间接(托管)连接?我以为当音频数据在源头可用时,固件应该生成
MESSAGE_MORE_DATA
,并且程序控制应该转移到aud_inp_handler()
,但是这没有发生。我应该指出,当我使用StreamConnect()
将源和宿连接在一起,但强行终止此连接时,固件会生成一条MESSAGE_STREAM_DISCONNECT
消息,该消息会被aud_inp_handler()
函数捕获,因此该函数本身已正确注册以检测固件消息,这使我相信音频不是一开始就从音频硬件传输到音频源缓冲区。 如何在此处建立源和接收器的间接(托管)连接?
#1 楼
该代码显示了从源到接收者的受控传输,但是请注意,我每100毫秒人工或独立地生成一条MESSAGE_MORE_DATA消息。 #include <panic.h>
#include <stdio.h>
#include <stream.h>
#include <pio.h>
#include <source.h>
#include <string.h>
#include <sink.h>
#include <csrtypes.h>
#include <connection.h>
#include <message.h>
#define VM_UART_(RATE) (uint16)((RATE*0.004096)+0.5)
#define VM_UART_RATE_1K2 0x0005
#define VM_UART_RATE_1K2 0x0005
#define VM_UART_RATE_2K4 0x000a
#define VM_UART_RATE_4K8 0x0014
#define VM_UART_RATE_76K8 0x013b
#define VM_UART_RATE_1843K2 0x1d7e
#define VM_UART_RATE_2764K8 0x2c3d
#define LED1 0x01 /* bit 1 */
#define DELAY1 200 /* ms */
#define LED2 0x02 /* bit 2 */
#define DELAY2 100 /* ms */
static void led_controller1( Task t, MessageId id, Message payload )
{
PioSet( LED1, (PioGet() ^ LED1) );
MessageSendLater( t, 0, 0, DELAY1 );
}
static void led_controller2( Task t, MessageId id, Message payload )
{
Source source= StreamUartSource();
uint16 length = SourceSize (source) ;
if(MESSAGE_MORE_DATA==id )
{
char *string;
uint16 offset;
uint8 *dest;
Sink sink=StreamUartSink();
PanicNull(sink);
string=(char *)SourceMap(source);
/* Claim space in the sink, getting the offset to it */
offset = SinkClaim(sink, length);
if(offset == 0xFFFF) Panic(); /* Space not available */
/* Map the sink into memory space */
dest = SinkMap(sink);
(void) PanicNull(dest);
/* Copy the string into the claimed space */
memcpy(dest+offset,SourceMap (source), length);
/* Flush the data out to the uart */
PanicZero(SinkFlush(sink, length));
SourceDrop (source, length);
}
PioSet( LED2, (PioGet() ^ LED2) );
MessageSendLater( t, MESSAGE_MORE_DATA, 0, DELAY2 );
}
static TaskData taskSPP1 ={led_controller1};
static TaskData taskSPP2 = {led_controller2};
int main(void)
{
PioSetDir(0xFF, 0xFF); /* Set all PIO to be output */
PioSet(0xFF, 0); /* Set all PIO off (0) */
MessageSend( &taskSPP1, 0 , 0 );
MessageSend( &taskSPP2, MESSAGE_MORE_DATA , 0 );
MessageLoop();
return 0;
评论
这不适用于音频源和音频接收器
–user17915
17年4月2日在11:09
#2 楼
发送之前,请使用以下函数:MessageSinkTask(Sink,task)
在方法main()中,在第一条消息之前。就我而言,它有所帮助。写下是否有帮助。例如,在您的情况下,它看起来像这样:MessageSinkTask(audSink_L,task)。
评论
这不适用于音频源和接收器
–user17915
17年4月3日,下午5:02
评论
我决定在任务中检查是否再有源字节的数目,如果没有更多的可能性来处理源并将结果发送给接收者。因为我是一个简单的无线电爱好者,所以我不知道这有多正确,但是对我来说这是有效的。可以帮到您。我说的是这样一个事实:如果系统不生成消息,则可以使用所需的指示符将它们独立发送到任务,从而保持循环性,每次检查接收器中字节的存在,无论UART或音频源。我仍然不明白为什么某些来源没有生成消息。
有些资源就是以此方式设计的。音频源不生成消息。 UART生成消息