7

After looking around this site and the meta (for example, here and here), I am assuming this question is on topic here (but let me know if it's not)

I am using CSR8675 Bluetooth chip with ADK4.0.1 (Audio Development Kit; the software suit for programming CSR audio chips)
(the chip will be used to connect with other devices using bluetooth, but this particular problem is not about bluetooth)

CSR's sample program shows how to do a direct connection between audio source and sink, but I want to do an indirect connection (to better understand the size and organization of the buffers involved when copying audio data from source to sink)

This is the modification I made to their sample code:

/*
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  

I have tried both enabling and disabling the block of code at /* BLOCK (1) */ with the same result

If I enable direct connection by enabling the line /* PanicFalse( StreamConnect(audSrc_L, audSink_L) ); */ then the audio from source to sink gets routed without any problems

How can I set up indirect (managed) connection of source and sink in this case? I was assuming that when audio data becomes available at the source, the firmware should generate MESSAGE_MORE_DATA and the program control should transfer into aud_inp_handler(), but it's not happening. I should point out that when I use StreamConnect() to connect the source and sink together, but forcefully terminate this connection, the firmware generates a MESSAGE_STREAM_DISCONNECT message, which gets captured by the aud_inp_handler() function, so the function itself has been registered properly to detect firmware messages, which leads me to believe that audio is not coming from the audio hardware to the audio source buffer in the first place.

How can I set up indirect (managed) connection of source and sink here?

3
  • I decided that it checked the number of bytes of the source, in the task, if there is no more possibility to process the source and send the result to the receiver. I do not know how much this is correct, since I am a simple radio lover, but it works in my case. Can to you as it helps. Apr 1, 2017 at 1:05
  • I'm talking about the fact that if the system does not generate messages, then they can be sent independently, with the desired indicator, to the task, thereby maintaining cyclicity, checking each time the presence of bytes in the receiver, regardless of the UART or Audio source. I still do not understand why messages are not generated for some kinds of sources. Apr 1, 2017 at 11:12
  • Some sources are designed in that way. Audio source does not generate messages. UART generates messages
    – user17915
    Apr 1, 2017 at 13:10

2 Answers 2

2

The code shows a controlled transfer from source to receiver, but notice that I artificially or independently generate a MESSAGE_MORE_DATA message every 100 milliseconds.

#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;
1
  • this is not for audio source and audio sink
    – user17915
    Apr 2, 2017 at 11:09
1

Before sending, use the function: MessageSinkTask (Sink,task) In the method main(), before the first message. In my case, it helped. Write if it helped you. For example, in your case it looks like this: MessageSinkTask (audSink_L,task).

1
  • 1
    this doesn't work with audio source and sink
    – user17915
    Apr 3, 2017 at 5:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.