This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Keil usb audio questions

Hi

if studied the keil usb-audio example: and there are two things I didn't understand. Maybe someone of you could give me some hints / explanations to these two code lines

DataIn &= B_S - 1;                    /* Adjust Data In Index */
if (((DataIn - DataOut) & (B_S - 1)) == (B_S/2)) {
     DataRun = 1;                        /* Data Stream running */
}

B_S = 1024 | DataIn shows the received data of the B_S pkt. But what means "adjust datain index? and why is the stream only running if the data pkt count size is B_S/2?

void USB_EndPoint3 (uint32_t event) {
#if USB_DMA
  USB_DMA_DESCRIPTOR DD;

  if (event & USB_EVT_OUT_DMA_EOT) {
    /* End of Transfer */
    if (USB_DMA_BufAdr(0x03) != ((uint32_t)DataBuf + 2*DataIn)) {
      /* Data Available */
      DataIn += P_C*P_S;                    /* Update Data In Index */
      DataIn &= B_S - 1;                    /* Adjust Data In Index */
      if (((DataIn - DataOut) & (B_S - 1)) == (B_S/2)) {
        DataRun = 1;                        /* Data Stream running */
      }
    } else {
      /* No Data */
      DataRun = 0;                          /* Data Stream not running */
      DataOut = DataIn;                     /* Initialize Data Indexes */
    }
  }
  if (event & (USB_EVT_OUT_DMA_EOT) | (USB_EVT_OUT_DMA_NDR)) {
    /* End of Transfer or New Descriptor Request */
    DD.BufAdr  = (uint32_t)DataBuf + 2*DataIn; /* DMA Buffer Address */
    DD.BufLen  = P_C;                       /* DMA Packet Count */
    DD.MaxSize = 0;                         /* Must be 0 for Iso Transfer */
    DD.InfoAdr = (uint32_t)InfoBuf;            /* Packet Info Buffer Address */
    DD.Cfg.Val = 0;                         /* Initial DMA Configuration */
    DD.Cfg.Type.IsoEP = 1;                  /* Iso Endpoint */
    USB_DMA_Setup (0x03, &DD);              /* Setup DMA */
    USB_DMA_Enable(0x03);                   /* Enable DMA */
  }
#else
  event = event;
#endif
}

best regards
Jan

Parents
  • When you have a ring buffer that is 2^n large, you can perform some tricks.

    The "normal" way to step the insertion index for a ring buffer is:

    buffer[in] = data;
    if (++in >= BUF_SIZE) in = 0;
    


    or maybe

    buffer[in] = data;
    in = ++in % BUF_SIZE;
    

    But as a special case, when BUF_SIZE is 2^n, you can do:

    buffer[in++ & (BUF_SIZE-1)] = data;
    

    Most probably, the USB code is letting the read and write indices just tick up and instead perform an and operation with (BUF_SIZE-1) whenever they need to index into the buffer.

    This would mean that:

    DataIn &= B_S - 1;                    /* Adjust Data In Index */
    


    is just a way to normalize DataIn as 0 <= DataIn < B_S before the code compares the input index with the output index.

    The second line probably just waits until you have buffered a bit of code before starting the transmission. Then you have 50% of the buffer size as safety margin to handle jitter.

    Think about normal CD music. The sample rate is 44100Hz. So the CD player will emit the data at this speed on a coaxial or optical output. But what happens if the DAC in the amplifier runs at a slightly different frequency? If the amplifier waits 50% of a buffer size before starting to play the music, it has 50% margin to accept more data in case the CD is slightly faster. And it has 50% buffer margin to play from the buffer in case the CD is slightly slower.

    Of course, I might be wrong about the 50% issue, since I haven't seen the full code.
    if (((DataIn - DataOut) & (B_S - 1)) == (B_S/2)) { DataRun = 1; /* Data Stream running */
    }

Reply
  • When you have a ring buffer that is 2^n large, you can perform some tricks.

    The "normal" way to step the insertion index for a ring buffer is:

    buffer[in] = data;
    if (++in >= BUF_SIZE) in = 0;
    


    or maybe

    buffer[in] = data;
    in = ++in % BUF_SIZE;
    

    But as a special case, when BUF_SIZE is 2^n, you can do:

    buffer[in++ & (BUF_SIZE-1)] = data;
    

    Most probably, the USB code is letting the read and write indices just tick up and instead perform an and operation with (BUF_SIZE-1) whenever they need to index into the buffer.

    This would mean that:

    DataIn &= B_S - 1;                    /* Adjust Data In Index */
    


    is just a way to normalize DataIn as 0 <= DataIn < B_S before the code compares the input index with the output index.

    The second line probably just waits until you have buffered a bit of code before starting the transmission. Then you have 50% of the buffer size as safety margin to handle jitter.

    Think about normal CD music. The sample rate is 44100Hz. So the CD player will emit the data at this speed on a coaxial or optical output. But what happens if the DAC in the amplifier runs at a slightly different frequency? If the amplifier waits 50% of a buffer size before starting to play the music, it has 50% margin to accept more data in case the CD is slightly faster. And it has 50% buffer margin to play from the buffer in case the CD is slightly slower.

    Of course, I might be wrong about the 50% issue, since I haven't seen the full code.
    if (((DataIn - DataOut) & (B_S - 1)) == (B_S/2)) { DataRun = 1; /* Data Stream running */
    }

Children