1
\$\begingroup\$

I have referred http://microchipdeveloper.com/harmony:i2s-tutorial and am able to configure the I2S and read continuous data from a microphone.

I am facing issue with the microphone data, and have been already discussing it here PIC32MZ: MSB of I2S data from digital microphone is always high. However, that is another issue altogether.

I have configured the I2S on DMA, and am able to continuously read the digital microphone data in my buffer.

My problem is, whenever I add a function to calculate the mean, average or to filter the DC offset from the data, my PIC32MZ program gets stuck.

I get the DMA interrupt, and there-by the I2S digital data once, but after that I never reach the breakpoint where I read the data.

Following is my code for reading data at the DMA interrupt:-

void APP_VOICE_RECORD_LOOP_BufferEventHandler(DRV_I2S_BUFFER_EVENT event,
        DRV_I2S_BUFFER_HANDLE handle, uintptr_t context)
{
// The context handle was set to an application specific
// object. It is now retrievable easily in the event handler.
//MY_APP_OBJ myAppObj = (MY_APP_OBJ *) contextHandle;
uint32_t convertedBufferCount = 0;
uint32_t evenCount = 0;

switch(event)
{
    case DRV_I2S_BUFFER_EVENT_COMPLETE:

        // This means the data was transferred.
        appVoiceRecordLoopData.codecClient.rxbufferObject = (uint32_t *) micbuf2;
        DRV_I2S_BufferAddRead(appVoiceRecordLoopData.codecClient.handle,
                appVoiceRecordLoopData.codecClient.txbufferObject,
                appVoiceRecordLoopData.codecClient.rxbufferObject,
                appVoiceRecordLoopData.codecClient.bufferSize);

        uint32_t receivedBufferSize = appVoiceRecordLoopData.codecClient.bufferSize / sizeof(uint32_t);

        for(evenCount = 0; evenCount < receivedBufferSize; evenCount++)
        {
            if(evenCount%2 == 0 && micbuf2[evenCount] != 0)
            {
                ConvertedAudioData[convertedBufferCount++] = (micbuf2[evenCount] >> 14);
            }
        }
        //uint32_t average = CalculateAverage(ConvertedAudioData, convertedBufferCount);
        appVoiceRecordLoopData.state = APP_VOICE_RECORD_LOOP_STATES_CODEC_WAIT_FOR_BUFFER_COMPLETE;
        break;

    case DRV_I2S_BUFFER_EVENT_ERROR:

        // Error handling here.
        break;

    case DRV_I2S_BUFFER_EVENT_ABORT:

        // Error handling here.
        break;    

    default:
        break;
}

}

Code works properly when I comment

//uint32_t average = CalculateAverage(ConvertedAudioData, convertedBufferCount);

However, when I uncomment this function, code never reaches here the second time.

Any suggestions what I might be doing wrongly here?

Thanks in advance

\$\endgroup\$
  • \$\begingroup\$ What does your CalculateAverage() routine do if convertedBufferCount is zero (particularly when doing the divide). \$\endgroup\$ – isdi Nov 30 '18 at 16:11
1
\$\begingroup\$

Chances are that this is called from within an ISR. The SPI engine is rather picky about over and under runs, you can see if this is happening by halting and viewing the corresponding SPI register. So while you are doing your intensive calcs the spi engine likely overruns, assuming you are using dma.

Harmony abstracts too many details. You can write an i2s driver in about 300 lines of code.

To fix this, I would suggest setting up a ping pong buffer, or some other method, and do your calculations outside of this time sensitive ISR.

\$\endgroup\$
  • \$\begingroup\$ Yes, this is correct answer. I will implement dma chaining/Ping-Pong buffer to solve my issue. Thanks a lot for the answer. Cheers! \$\endgroup\$ – Sandrocottus Dec 3 '18 at 9:43
1
\$\begingroup\$

Exactly which line doesn't it get to? Usually when I run into these instances, I'll step through the assembly to see what register the processor is unable to read.

However, just looking at the code you've posted, I'm suspicious of where the array ConvertedAudioData is defined. It's possible the compiler is treating this as "implicitly declared", putting the data on the stack, and by the time you leave the scope of that for() loop it's invalid.

\$\endgroup\$
  • \$\begingroup\$ Hi Drewster, thanks a lot for providing an answer. I have defined ConvertedAudioData array as globally, similar to the micbuf1 and micbuf2 arrays. Should I declare ConvertedAudioData as local to the APP_VOICE_RECORD_LOOP_BufferEventHandler? \$\endgroup\$ – Sandrocottus Nov 30 '18 at 16:47
  • \$\begingroup\$ At the very least I would try that as an intermediate step - even if it doesn't solve your issue. Especially when you're trying to increment through arrays, etc. it's best if those arrays are explicitly in your file scope, and you simply have get() and set() functions to interact with other files outside of scope. When you're manipulating an array from another (global) scope, you're really just hoping that nobody screwed up with your pointer (which is all an array really is in c) Again, stepping through to see exactly which instruction blows up might be very helpful here \$\endgroup\$ – Drewster Nov 30 '18 at 20:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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