drivers/audio: Fix audio tone generator

The audio tone generator stopped working with the 'echo' command
since https://github.com/apache/nuttx-apps/pull/1559

Before that PR:

nsh> echo "t120o1l16b9n0baan0bn0bn0baaan0b9n0baan0b" > /dev/tone0
tone_write: Received 41 bytes
nsh>

After that PR:

nsh> echo "t120o1l16b9n0baan0bn0bn0baaan0b9n0baan0b" > /dev/tone0
tone_write: Received 40 bytes
tone_write: Received 1 bytes
nsh>

Unfortunately the Audio Tone was not block new write attempts even
when it was already playing a melody.

This commit fix it and avoids the issue caused by that PR.

Signed-off-by: Alan C. Assis <acassis@gmail.com>
This commit is contained in:
Alan Carvalho de Assis 2026-06-26 10:38:31 -03:00 committed by Alan C. Assis
parent 578b303c63
commit 861125a75e

View file

@ -86,6 +86,7 @@ struct tone_upperhalf_s
uint8_t channel; /* Output channel that drives the tone. */
volatile bool started; /* True: pulsed output is being generated */
mutex_t lock; /* Supports mutual exclusion */
sem_t busysem; /* Don't accept new writes if busy */
struct pwm_info_s tone; /* Pulsed output for Audio Tone */
struct pwm_lowerhalf_s *devtone;
struct oneshot_lowerhalf_s *oneshot;
@ -665,6 +666,10 @@ tune_end:
else
{
g_tune = NULL;
/* Now the user can play again */
nxsem_post(&upper->busysem);
}
}
@ -860,6 +865,7 @@ static ssize_t tone_write(FAR struct file *filep, FAR const char *buffer,
{
FAR struct inode *inode = filep->f_inode;
FAR struct tone_upperhalf_s *upper = inode->i_private;
int ret;
/* We need to receive a string #RRGGBB = 7 bytes */
@ -877,6 +883,15 @@ static ssize_t tone_write(FAR struct file *filep, FAR const char *buffer,
return -EINVAL;
}
/* If it is playing, then ignore new write attempts */
ret = nxsem_wait_uninterruptible(&upper->busysem);
if (ret < 0)
{
auderr("ERROR: Audio Tone is already playing, try again later!\n");
return -EAGAIN;
}
/* Copy music to internal buffer */
memcpy(tune_buf, buffer, buflen);
@ -940,6 +955,7 @@ int tone_register(FAR const char *path, FAR struct pwm_lowerhalf_s *tone,
*/
nxmutex_init(&upper->lock);
nxsem_init(&upper->busysem, 0, 1);
upper->devtone = tone;
upper->oneshot = oneshot;
upper->channel = (uint8_t)channel;