• AVR Freaks

Hot!I2S DMA Left Channel Data Only

Author
embedded_guy12am
New Member
  • Total Posts : 13
  • Reward points : 0
  • Joined: 2019/08/31 10:12:14
  • Location: 0
  • Status: offline
2020/06/22 18:40:19 (permalink)
0

I2S DMA Left Channel Data Only

I am using the pic32mz and have an application where the I2S data is being transferred in/out using DMA. I was wondering if anyone knows if the SPI/I2S and/or DMA can be setup to transfer only one channel only (left or right) of the data.
 
Any help is appreciated.
 
Thanks.
#1

16 Replies Related Threads

    MisterHemi
    Super Member
    • Total Posts : 255
    • Reward points : 0
    • Joined: 2017/11/02 12:24:21
    • Location: Commerce, CA USA
    • Status: offline
    Re: I2S DMA Left Channel Data Only 2020/06/22 22:18:39 (permalink)
    0
    There is a mode for mono audio, however it just transmits the same data for both channels.
     
    From the data sheet:
    AUDMONO: Transmit Audio Data Format bit (1,2)
    1 = Audio data is mono (Each data word is transmitted on both left and right channels) 
    0 = Audio data is stereo

    My configuration:
    MacBook Pro (Retina, 15-inch, Mid 2015) with MacOS Mojave (10.14.6) and MPLAB X IDE v5.30
     
    Curiosity PIC32MZ EF 1 & 2, PIC24F Curiosity, XPRESS EVAL BOARD (PIC16F18855), SAMA5D3 Xplained and various custom boards.
    #2
    friesen
    Super Member
    • Total Posts : 2140
    • Reward points : 0
    • Joined: 2008/05/08 05:23:35
    • Location: Indiana, USA
    • Status: offline
    Re: I2S DMA Left Channel Data Only 2020/06/23 05:04:23 (permalink)
    0
    For in, you can use two dma channels, one dma to a trash channel of short length, auto restarting.
     
    For out, its pretty cheap to use the mono bit, assuming you are just using a standard off the shelf dac with LR channels.

    Attached Image(s)


    Erik Friesen
    #3
    embedded_guy12am
    New Member
    • Total Posts : 13
    • Reward points : 0
    • Joined: 2019/08/31 10:12:14
    • Location: 0
    • Status: offline
    Re: I2S DMA Left Channel Data Only 2020/06/23 07:04:23 (permalink)
    0
    MisterHemi
    There is a mode for mono audio, however it just transmits the same data for both channels. From the data sheet:AUDMONO: Transmit Audio Data Format bit (1,2)
    1 = Audio data is mono (Each data word is transmitted on both left and right channels) 0 = Audio data is stereo


    Right. I saw this previously. But this is for transmit only and I think the dma and i2s will require the data to be in the buffer as 16-bit left channel followed by 16-bit right channel. I don't know that the dma will use each buffer element on both channels.
    #4
    friesen
    Super Member
    • Total Posts : 2140
    • Reward points : 0
    • Joined: 2008/05/08 05:23:35
    • Location: Indiana, USA
    • Status: offline
    Re: I2S DMA Left Channel Data Only 2020/06/23 07:48:07 (permalink)
    0
    I'm not sure you understand this. For tx, the mono thing is transparent to the dma, you only need to feed one channel. For the adc, you set the tx length to match your bit size. Typical L R application uses two dma channels and buffers.

    Erik Friesen
    #5
    embedded_guy12am
    New Member
    • Total Posts : 13
    • Reward points : 0
    • Joined: 2019/08/31 10:12:14
    • Location: 0
    • Status: offline
    Re: I2S DMA Left Channel Data Only 2020/06/23 08:47:17 (permalink)
    0
    friesen
    For in, you can use two dma channels, one dma to a trash channel of short length, auto restarting.
     
    For out, its pretty cheap to use the mono bit, assuming you are just using a standard off the shelf dac with LR channels.




     
    Thanks for the code, Erik. You're right, I'm trying to understand. I'll test out the AUDMONO bit for the transmit. Restatements are for my own confirmation trying to understand what's going on in your code. 
     
    If I have a buffer
     
    int16_t data_buffer[ 10 ];
     
    then without AUDMONO set, the tx dma will transmit in the first i2s frame data_buffer[0] on left, data_buffer[1] on right, in the second i2s frame data_buffer[2] on left, data_buffer[3] on right, and so on.
    With AUDMONO set, the tx dma will transmit in the first i2s frame data_buffer[0] on the left and right channels, in the second i2s frame data_buffer[1] on the left and right channels, and so on?
     
    Both dma channels are using the SPI1 RX interrupt to start and reading from SPI1BUF, channel 1 has a lower priority than channel 2.
     
    How does the dma ch1 know how to skip the right channel data?
     
    I see dma ch 2 does not have any ISR, I presume to avoid constant interrupts for every 16-bit right channel input.
     
    Can you show your ISRs for the DMA channels (or describe what they're doing).
     
    Thanks
    #6
    friesen
    Super Member
    • Total Posts : 2140
    • Reward points : 0
    • Joined: 2008/05/08 05:23:35
    • Location: Indiana, USA
    • Status: offline
    Re: I2S DMA Left Channel Data Only 2020/06/23 12:20:59 (permalink)
    0
    It doesn't 'know' to skip, it just gets done with it's part and let's the other channel do its thing. Honestly the best way to learn is to fiddle with it until it does what you want. Remember that the master typically is operating the LR pin, so if you get a sequence that works it should be repeatable.

    The isr basically just refills the buffer and restarts dma. I'm not where I have access to my code right now.

    Erik Friesen
    #7
    friesen
    Super Member
    • Total Posts : 2140
    • Reward points : 0
    • Joined: 2008/05/08 05:23:35
    • Location: Indiana, USA
    • Status: offline
    Re: I2S DMA Left Channel Data Only 2020/06/23 12:22:47 (permalink)
    0
    I should add, it basically knows because the dma transfer size is 2 bytes, the transfer is done.

    Erik Friesen
    #8
    friesen
    Super Member
    • Total Posts : 2140
    • Reward points : 0
    • Joined: 2008/05/08 05:23:35
    • Location: Indiana, USA
    • Status: offline
    Re: I2S DMA Left Channel Data Only 2020/06/23 12:29:43 (permalink)
    0
    Here is my ISR code
     
    void DmaHandler1(void) {
        int HP = AdcHeadPtr & ADC_Ptr_Mask; //Prevent partial loads
        int TP = AdcTailPtr & ADC_Ptr_Mask;
        int ReadySpace;
        if (HP == TP) {
     ReadySpace = ADC_RxBuffSize - ADC_Rx_Dma_Size; //ADC_UsableBuff;
        } else {
     if (HP > TP) {
         ReadySpace = ADC_RxBuffSize - (HP - TP) - ADC_Rx_Dma_Size;
     } else {
         ReadySpace = TP - HP - ADC_Rx_Dma_Size;
     }
        }

        if (ReadySpace == 0) {
     UnderRun = -1;
     DCH1DSA = KVA_TO_PA(&datadump); //Source
        } else {
     AdcHeadPtr += ADC_Rx_Dma_Size;
     if (AdcHeadPtr == ADC_RxBuffSize) {
         AdcHeadPtr = 0;
     }
     DCH1DSA = KVA_TO_PA(&rxBuffer[AdcHeadPtr]); //Source
        }
        IFS4CLR = _IFS4_DMA1IF_MASK;
        DCH1INTCLR = _DCH1INT_CHBCIF_MASK;
        DCH1CONSET = _DCH1CON_CHEN_MASK;
    }


    Erik Friesen
    #9
    friesen
    Super Member
    • Total Posts : 2140
    • Reward points : 0
    • Joined: 2008/05/08 05:23:35
    • Location: Indiana, USA
    • Status: offline
    Re: I2S DMA Left Channel Data Only 2020/06/23 12:32:09 (permalink)
    0
    I guess I better add some of my definitions.  I spent some memory for datadump, not quite like I was saying.
     
     
    static volatile PCM_SHORT rxBuffer[ADC_RxBuffSize] __attribute__((aligned(4), coherent));
    static PCM_SHORT datadump[ADC_Rx_Dma_Size]__attribute__((aligned(4), coherent));
    static volatile int AdcHeadPtr = 0, AdcTailPtr = 0;
    static PCM_SHORT channeldump __attribute__((aligned(4), coherent));


    Erik Friesen
    #10
    embedded_guy12am
    New Member
    • Total Posts : 13
    • Reward points : 0
    • Joined: 2019/08/31 10:12:14
    • Location: 0
    • Status: offline
    Re: I2S DMA Left Channel Data Only 2020/06/25 18:30:10 (permalink)
    0
    I get that the transfer is 2 bytes (presuming the left channel data), but the next transfer is also 2 bytes from the spi buffer and those next two bytes should be the right channel.
    #11
    friesen
    Super Member
    • Total Posts : 2140
    • Reward points : 0
    • Joined: 2008/05/08 05:23:35
    • Location: Indiana, USA
    • Status: offline
    Re: I2S DMA Left Channel Data Only 2020/06/25 18:35:16 (permalink)
    0
    I don't remember why it works anymore, some billions? of successes later.

    Erik Friesen
    #12
    Stefiff
    Starting Member
    • Total Posts : 84
    • Reward points : 0
    • Joined: 2012/07/15 15:26:29
    • Location: 0
    • Status: offline
    Re: I2S DMA Left Channel Data Only 2020/06/26 00:26:19 (permalink)
    4 (1)
    There is something you are missing. The audio interface is standard /I2S/. In this standard, the two channels - left / right - are always transmitted sequentially. There are several variants of this standard, but both channels are always transmitted. Outside is a chip, a codec that converts this data into sound. There is no codec that recognizes incoming data for only one channel. It always expects a standard input stream, alternating two channels. Whether this codec will use the information from both channels, or only from one, depends on it.
    The conversion from the internal buffer, in a format according to this standard, is performed by the SPI module. DMA does not determine anything. DMA is only used to replace the CPU in the process of loading data into the FIFO of the SPI. Only so. You can easily make sound without DMA, but your CPU will be very busy.
    That is, the SPI module will always use two bytes for one channel, and two bytes for the other channel. If you switch it to mono mode, it will copy two bytes to both channels, it will repeat them. But it will still send both channels to the codec. What you put in the RAM buffer so that the DMA can loaded this into the FIFO of the SPI, already depends on your software.
     
    For example, the codec will use only one channel, then in the RAM buffer you put the data for only one channel. Values for the other do not matter.
    DxL, DxL, 0,0 , DxL, DxL …. - for left channel, for example.
    If you ONLY want to play sound, whether it's one or two channels, you only need one DMA.
     
    There is only one direction:
    encoded data, RAM > CPU decode function>decoded data, RAM>DMA RAM to FIFO SPI> SPI to codec.
     
    SPI set to set ISR flag /_SPI4_TX_VECTOR/ when STXISEL=11/not full/
    In DMA module is set to put data from the FIFO flag _SPI4_TX_VECTOR (for SPI4 for example). The interrupt for DMA is when DMA sends everything and needs to switch to the other send buffer. _IFS4_DMA2IF_MASK (for DMA2 for example).
     
     
    #13
    embedded_guy12am
    New Member
    • Total Posts : 13
    • Reward points : 0
    • Joined: 2019/08/31 10:12:14
    • Location: 0
    • Status: offline
    Re: I2S DMA Left Channel Data Only 2020/06/27 08:47:16 (permalink)
    4 (1)
    Stefiff
    There is something you are missing. The audio interface is standard /I2S/. In this standard, the two channels - left / right - are always transmitted sequentially. There are several variants of this standard, but both channels are always transmitted. Outside is a chip, a codec that converts this data into sound. There is no codec that recognizes incoming data for only one channel. It always expects a standard input stream, alternating two channels. Whether this codec will use the information from both channels, or only from one, depends on it.
    The conversion from the internal buffer, in a format according to this standard, is performed by the SPI module. DMA does not determine anything. DMA is only used to replace the CPU in the process of loading data into the FIFO of the SPI. Only so. You can easily make sound without DMA, but your CPU will be very busy.
    That is, the SPI module will always use two bytes for one channel, and two bytes for the other channel. If you switch it to mono mode, it will copy two bytes to both channels, it will repeat them. But it will still send both channels to the codec. What you put in the RAM buffer so that the DMA can loaded this into the FIFO of the SPI, already depends on your software.

     
    Thanks for the response. Yeah, there are some things I'm missing.
     
    I have 4 dma channels I'm using, two RX and two TX. The pic32mz is in the middle processing the incoming data, then sending out the post-processed data. The higher-level application expects mono data, one (left) channel only.
     
    I understand the dma is just transferring bytes in and out. I am trying, as you mentioned, to limit the impact on the pic32mz and see if I can setup the pic32 spi/i2s module port to handle the data xfer as I need it by configuring the port correctly for my application.
     
     
    Stefiff 
    For example, the codec will use only one channel, then in the RAM buffer you put the data for only one channel. Values for the other do not matter.
    DxL, DxL, 0,0 , DxL, DxL …. - for left channel, for example.
    If you ONLY want to play sound, whether it's one or two channels, you only need one DMA.

     
    Ok. This is one thing I was wondering -- does the output buffer for TX data in mono mode (AUDMONO) need to have data as
    [16-bit LEFT] [16-bit RIGHT=0] [16-bit LEFT] [16-bit RIGHT=0] ...
    or
    [16-bit LEFT] [16-bit LEFT] [16-bit LEFT] ...
     
     
     
     



    #14
    Stefiff
    Starting Member
    • Total Posts : 84
    • Reward points : 0
    • Joined: 2012/07/15 15:26:29
    • Location: 0
    • Status: offline
    Re: I2S DMA Left Channel Data Only 2020/06/27 12:05:53 (permalink)
    0
    TX Buffer [16-bit 0] [16-bit 1] [16-bit 2] [16-bit 3]
    The output from SPI port [16-bit 0, as left] [16-bit 0, as right]…. [16-bit 3, as left] [16-bit 3, as right]
    ====
    The other thing is to check actually, what is coming out of the port pin with a logic analyzer, because the description of the bits does not correspond to reality. :)
    post edited by Stefiff - 2020/06/27 12:14:08
    #15
    embedded_guy12am
    New Member
    • Total Posts : 13
    • Reward points : 0
    • Joined: 2019/08/31 10:12:14
    • Location: 0
    • Status: offline
    Re: I2S DMA Left Channel Data Only 2020/06/27 13:32:03 (permalink)
    0
    Stefiff
    TX Buffer [16-bit 0] [16-bit 1] [16-bit 2] [16-bit 3]
    The output from SPI port [16-bit 0, as left] [16-bit 0, as right]…. [16-bit 3, as left] [16-bit 3, as right]
    ====

     
    Right. Ok
     
    Stefiff
    The other thing is to check actually, what is coming out of the port pin with a logic analyzer, because the description of the bits does not correspond to reality. :)

     
    Really? The data might be different
    #16
    Stefiff
    Starting Member
    • Total Posts : 84
    • Reward points : 0
    • Joined: 2012/07/15 15:26:29
    • Location: 0
    • Status: offline
    Re: I2S DMA Left Channel Data Only 2020/06/27 14:25:46 (permalink)
    0
    Unfortunately, yes. I specifically use Left Justified mode, and the description is quite far from the truth. Half of the bits as described should not affect the output signal, but in practice affect.
    In the end, it turned out that I had to externally delay one signal in order for the codec to work properly. 20 ns, but it was impossible without it.
    For this I wrote, “draw the signal” that is required for your device, varying with the bits.
    #17
    Jump to:
    © 2020 APG vNext Commercial Version 4.5