WM8904: Don't use MSEC2TICK in timeout calculation

This commit is contained in:
Gregory Nutt 2014-08-08 11:02:45 -06:00
parent 8b69cb3ea2
commit 6e0acd7cd4
3 changed files with 32 additions and 28 deletions

View File

@ -1426,6 +1426,7 @@ static int wm8904_sendbuffer(FAR struct wm8904_dev_s *priv)
FAR struct ap_buffer_s *apb;
irqstate_t flags;
uint32_t timeout;
int shift;
int ret = OK;
/* Loop while there are audio buffers to be sent and we have few than
@ -1461,27 +1462,30 @@ static int wm8904_sendbuffer(FAR struct wm8904_dev_s *priv)
/* Send the entire audio buffer via I2S. What is a reasonable timeout
* to use? This would depend on the bit rate and size of the buffer.
*
* Samples in the buffer:
* = buffer_size * 8 / bpsamp samples
* Expected transfer time:
* = samples / samprate seconds
* = (samples * 1000) / (samprate * msec_per_tick) ticks
* = (buffer_size * 8000) /(samprate * bpsamp * msec_per_tick)
* Samples in the buffer (samples):
* = buffer_size * 8 / bpsamp samples
* Sample rate (samples/second):
* = samplerate * nchannels
* Expected transfer time (seconds):
* = (buffer_size * 8) / bpsamp / samplerate / nchannels
*
* We will set the timeout about twice that. Here is a reasonable
* approximation that saves a multiply:
* = (buffer_size * 16384) /(samprate * bpsamp * msec_per_tick)
* We will set the timeout about twice that.
*
* REVISIT: Does this take into account the number channels? Perhaps
* saving an reusing the bitrate would give a better and simpler
* calculation.
* NOTES:
* - The multiplier of 8 becomes 16000 for 2x and units of
* milliseconds.
* - 16000 is a approximately 16384 (1 << 14), bpsamp is either
* (1 << 3) or (1 << 4), and nchannels is either (1 << 0) or
* (1 << 1). So this can be simplifies to (milliseconds):
*
* REVISIT: Should not use MSEC_PER_TICK. It can be inaccurate with
* microsecond resolution timer.
* = (buffer_size << shift) / samplerate
*/
timeout = (((uint32_t)(apb->nbytes - apb->curbyte) << 14) /
((uint32_t)priv->samprate * MSEC_PER_TICK * priv->bpsamp));
shift = (priv->bpsamp == 8) ? 14 - 3 : 14 - 4;
shift -= (priv->nchannels > 1) ? 1 : 0;
timeout = MSEC2TICK(((uint32_t)(apb->nbytes - apb->curbyte) << shift) /
(uint32_t)priv->samprate);
ret = I2S_SEND(priv->i2s, apb, wm8904_senddone, priv, timeout);
if (ret < 0)

View File

@ -55,7 +55,7 @@
* The code in this execution context can access the kernel global data
* directly if: (1) we are not running tick-less (in which case there is
* no global timer data), (2) this is an un-protected, non-kernel build, or
* (2) this is a protectd build, but this code is being built for execution
* (2) this is a protected build, but this code is being built for execution
* within the kernel space.
*/
@ -89,16 +89,16 @@
#define NSEC_PER_USEC 1000
/* If CONFIG_SCHED_TICKLESS is not defined, then the interrupt interval of
* the system timer is given by MSEC_PER_TICK. This is the expected number
* of milliseconds between calls from the processor-specific logic to
* sched_process_timer(). The default value of MSEC_PER_TICK is 10
* milliseconds (100KHz). However, this default setting can be overridden
* the system timer is given by USEC_PER_TICK. This is the expected number
* of microseconds between calls from the processor-specific logic to
* sched_process_timer(). The default value of USEC_PER_TICK is 10000
* microseconds (100KHz). However, this default setting can be overridden
* by defining the interval in microseconds as CONFIG_USEC_PER_TICK in the
* NuttX configuration file.
*
* The following calculations are only accurate when (1) there is no
* truncation involved and (2) the underlying system timer is an even
* multiple of milliseconds. If (2) is not true, you will probably want
* multiple of microseconds. If (2) is not true, you will probably want
* to redefine all of the following.
*/
@ -114,7 +114,7 @@
*/
#define TICK_PER_DSEC (USEC_PER_DSEC / USEC_PER_TICK) /* Truncates! */
#define TICK_PER_SEC (USEC_PER_SEC / USEC_PER_TICK) /* Truncates! */
#define TICK_PER_SEC (USEC_PER_SEC / USEC_PER_TICK) /* Truncates! */
#define TICK_PER_MSEC (USEC_PER_MSEC / USEC_PER_TICK) /* Truncates! */
#define MSEC_PER_TICK (USEC_PER_TICK / USEC_PER_MSEC) /* Truncates! */
#define NSEC_PER_TICK (USEC_PER_TICK * NSEC_PER_USEC) /* Exact */
@ -128,11 +128,11 @@
# define MSEC2TICK(msec) USEC2TICK(msec * 1000) /* Rounds */
#endif
#define DSEC2TICK(dsec) MSEC2TICK((dsec)*MSEC_PER_DSEC) /* Exact */
#define SEC2TICK(sec) MSEC2TICK((sec)*MSEC_PER_SEC) /* Exact */
#define DSEC2TICK(dsec) MSEC2TICK((dsec) * MSEC_PER_DSEC) /* Rounds */
#define SEC2TICK(sec) MSEC2TICK((sec) * MSEC_PER_SEC) /* Rounds */
#define TICK2NSEC(tick) ((tick)*NSEC_PER_TICK) /* Exact */
#define TICK2USEC(tick) ((tick)*USEC_PER_TICK) /* Exact */
#define TICK2NSEC(tick) ((tick) * NSEC_PER_TICK) /* Exact */
#define TICK2USEC(tick) ((tick) * USEC_PER_TICK) /* Exact */
#if (MSEC_PER_TICK * USEC_PER_MSEC) == USEC_PER_TICK
# define TICK2MSEC(tick) ((tick)*MSEC_PER_TICK) /* Exact */

View File

@ -174,7 +174,7 @@ void apb_free(FAR struct ap_buffer_s *apb)
if (refcount <= 1)
{
auddbg("Freeing %p\n", apb);
audvdbg("Freeing %p\n", apb);
lib_ufree(apb);
}
}