diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2013-05-21 13:13:05 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2013-05-21 13:13:05 -0600 |
commit | 801977de7c84d03616329795e1c59929ab948906 (patch) | |
tree | b9d9220000c01cf9aca8e010f43fc488ccc26f26 | |
parent | 3895e0ec4c2c3057935bbeb7558fa4b815385334 (diff) | |
download | nuttx-801977de7c84d03616329795e1c59929ab948906.tar.gz nuttx-801977de7c84d03616329795e1c59929ab948906.tar.bz2 nuttx-801977de7c84d03616329795e1c59929ab948906.zip |
Audio subystem update from Ken Pettit. Plus moved some header files
-rw-r--r-- | nuttx/ChangeLog | 6 | ||||
-rw-r--r-- | nuttx/arch/arm/src/stm32/chip.h | 2 | ||||
-rw-r--r-- | nuttx/audio/Kconfig | 32 | ||||
-rw-r--r-- | nuttx/audio/audio.c | 177 | ||||
-rw-r--r-- | nuttx/audio/buffer.c | 2 | ||||
-rw-r--r-- | nuttx/audio/pcm.c | 2 | ||||
-rw-r--r-- | nuttx/configs/mikroe-stm32f4/src/Makefile | 4 | ||||
-rw-r--r-- | nuttx/configs/mikroe-stm32f4/src/mikroe-stm32f4-internal.h | 23 | ||||
-rw-r--r-- | nuttx/configs/mikroe-stm32f4/src/up_nsh.c | 21 | ||||
-rw-r--r-- | nuttx/configs/mikroe-stm32f4/src/up_spi.c | 15 | ||||
-rw-r--r-- | nuttx/configs/mikroe-stm32f4/src/up_vs1053.c | 200 | ||||
-rw-r--r-- | nuttx/configs/open1788/README.txt | 30 | ||||
-rw-r--r-- | nuttx/drivers/audio/vs1053.c | 161 | ||||
-rw-r--r-- | nuttx/drivers/audio/vs1053.h | 222 | ||||
-rw-r--r-- | nuttx/include/nuttx/audio/audio.h (renamed from nuttx/include/nuttx/audio.h) | 63 | ||||
-rw-r--r-- | nuttx/include/nuttx/audio/vs1053.h | 122 | ||||
-rw-r--r-- | nuttx/include/nuttx/spi.h | 3 |
17 files changed, 979 insertions, 106 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 70ae0e381..aaef727c5 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -4761,3 +4761,9 @@ * configs/lm3s6965-ek/discover: Add an example configuration for UDP discovery tool on the lm3s6965-ek board. From Max Holtberg (2013-5-21). + * audio/, drivers/audio, include/nuttx/audio: Added a callback interface + to the Audio upperhalf driver for dequeueing, reporting async events, + etc. Also included is some initial work for the VS1053 driver. From + Ken Pettit (2013-5-21). + * include/nuttx/audio/audio.h: Moved from include/nuttx/ to include/nuttx/audio. + (2013-5-21).
\ No newline at end of file diff --git a/nuttx/arch/arm/src/stm32/chip.h b/nuttx/arch/arm/src/stm32/chip.h index d498162b7..dead451b5 100644 --- a/nuttx/arch/arm/src/stm32/chip.h +++ b/nuttx/arch/arm/src/stm32/chip.h @@ -87,7 +87,7 @@ /* STM32F103ZC, STM32F103ZD, and STM32F103ZE are all provided in 144 pin packages and differ * only in the available FLASH and SRAM. */ -# elif defined(CONFIG_ARCH_CHIP_STM32F103ZET6) +# elif defined(CONFIG_ARCH_CHIP_STM32F103ZET6) # include "chip/stm32f103ze_pinmap.h" /* STM32 F105/F107 Connectivity Line */ diff --git a/nuttx/audio/Kconfig b/nuttx/audio/Kconfig index a666c775f..7ce503aaf 100644 --- a/nuttx/audio/Kconfig +++ b/nuttx/audio/Kconfig @@ -27,6 +27,36 @@ config AUDIO_LARGE_BUFFERS 32-bit max sample count for increased samples / buffer capability. channel capability. +config AUDIO_CUSTOM_DEV_PATH + bool "Use custom device path" + default n + ---help--- + By default, all audio devices on the target are are registered in the + /dev/audio directory. Select this option to change the default location + for the device registration. + +if AUDIO_CUSTOM_DEV_PATH + +config AUDIO_DEV_ROOT + bool "Place audio devices in /dev" + default n + ---help--- + This option causes all device entries to appear in /dev with all the + other device entries. This option generates the smallest code and + RAM footprint. + +if !AUDIO_DEV_ROOT + +config AUDIO_DEV_PATH + string "Base path for Audio devices" + default "/dev/audio" + ---help--- + The path on the target where audio devices are registered. The default + is to place all audio devices in the /dev/audio/ directory. + +endif +endif + menu "Supported Audio Formats" config AUDIO_FORMAT_PCM @@ -55,7 +85,7 @@ config AUDIO_FORMAT_OGG_VORBIS endmenu -# These are here as placeholders of what could be added +# These are here as placeholders of what could be added if CONFIG_AUDIO_PLANNED diff --git a/nuttx/audio/audio.c b/nuttx/audio/audio.c index 4457294f9..444412c97 100644 --- a/nuttx/audio/audio.c +++ b/nuttx/audio/audio.c @@ -59,7 +59,7 @@ #include <nuttx/kmalloc.h> #include <nuttx/fs/fs.h> #include <nuttx/arch.h> -#include <nuttx/audio.h> +#include <nuttx/audio/audio.h> #include <arch/irq.h> @@ -94,12 +94,14 @@ struct audio_upperhalf_s * Private Function Prototypes ****************************************************************************/ -static int audio_open(FAR struct file *filep); -static int audio_close(FAR struct file *filep); -static ssize_t audio_read(FAR struct file *filep, FAR char *buffer, size_t buflen); -static ssize_t audio_write(FAR struct file *filep, FAR const char *buffer, size_t buflen); -static int audio_start(FAR struct audio_upperhalf_s *upper, unsigned int oflags); -static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg); +static int audio_open(FAR struct file *filep); +static int audio_close(FAR struct file *filep); +static ssize_t audio_read(FAR struct file *filep, FAR char *buffer, size_t buflen); +static ssize_t audio_write(FAR struct file *filep, FAR const char *buffer, size_t buflen); +static int audio_start(FAR struct audio_upperhalf_s *upper, unsigned int oflags); +static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg); +static void audio_callback(FAR void *priv, uint16_t reason, + FAR struct ap_buffer_s *apb, uint16_t status); /**************************************************************************** * Private Data @@ -169,7 +171,7 @@ static int audio_open(FAR struct file *filep) errout_with_sem: sem_post(&upper->exclsem); - + errout: return ret; } @@ -226,7 +228,7 @@ static int audio_close(FAR struct file *filep) //errout_with_sem: sem_post(&upper->exclsem); - + errout: return ret; } @@ -264,7 +266,7 @@ static ssize_t audio_write(FAR struct file *filep, FAR const char *buffer, size_ * * Description: * Handle the AUDIOIOC_START ioctl command - * + * ************************************************************************************/ static int audio_start(FAR struct audio_upperhalf_s *upper, unsigned int oflags) @@ -302,7 +304,7 @@ static int audio_start(FAR struct audio_upperhalf_s *upper, unsigned int oflags) * * Description: * The standard ioctl method. This is where ALL of the Audio work is done. - * + * ************************************************************************************/ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg) @@ -351,7 +353,8 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg) audvdbg("AUDIOIOC_INITIALIZE: Device=%d", caps->ac_type); /* Call the lower-half driver configure handler */ - ret = lower->ops->configure(lower, caps); + + ret = lower->ops->configure(lower, caps, &audio_callback, upper); } break; @@ -374,7 +377,7 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg) case AUDIOIOC_START: { - audvdbg("AUDIOIOC_START\n"); + audvdbg("AUDIOIOC_START\n"); DEBUGASSERT(lower->ops->start != NULL); /* Start the pulse train */ @@ -434,8 +437,8 @@ static int audio_ioctl(FAR struct file *filep, int cmd, unsigned long arg) * Input parameters: * path - The full path to the driver to be registers in the NuttX pseudo- * filesystem. The recommended convention is to name Audio drivers - * based on the function they provide, such as "/dev/pcm0", "/dev/mp31", - * etc. + * based on the function they provide, such as "/dev/pcm0", "/dev/mp31", + * etc. * dev - A pointer to an instance of lower half audio driver. This instance * is bound to the Audio driver and must persists as long as the driver * persists. @@ -450,7 +453,13 @@ int audio_register(FAR const char *name, FAR struct audio_lowerhalf_s *dev) FAR struct audio_upperhalf_s *upper; char path[AUDIO_MAX_DEVICE_PATH]; static bool dev_audio_created = false; +#ifndef CONFIG_AUDIO_CUSTOM_DEV_PATH const char* devname = "/dev/audio"; +#elif !defined(CONFIG_AUDIO_DEV_ROOT) + const char* devname = CONFIG_AUDIO_DEV_PATH; + const char* ptr; + char* pathptr; +#endif /* Allocate the upper-half data structure */ @@ -466,6 +475,80 @@ int audio_register(FAR const char *name, FAR struct audio_lowerhalf_s *dev) sem_init(&upper->exclsem, 0, 1); upper->dev = dev; +#ifdef CONFIG_AUDIO_CUSTOM_DEV_PATH + +#ifdef CONFIG_AUDIO_DEV_ROOT + + /* This is the simple case ... No need to make a directory */ + + strcpy(path, "/dev/"); + strcat(path, name); + +#else + /* Ensure the path begins with "/dev" as we don't support placing device + * anywhere but in the /dev directory + */ + + DEBUGASSERT(strncmp(devname, "/dev", 4) == 0); + + /* Create a /dev/audio directory. */ + + if (!dev_audio_created) + { + /* Get path name after "/dev" */ + + ptr = &devname[4]; + if (*ptr == '/') + { + ptr++; + } + + strcpy(path, "/dev/"); + pathptr = &path[5]; + + /* Do mkdir for each segment of the path */ + + while (*ptr != '\0') + { + /* Build next path segment into path variable */ + + while (*ptr != '/' && *ptr != '\0') + { + *pathptr++ = *ptr++; + } + *pathptr = '\0'; + + /* Make this level of directory */ + + mkdir(path, 0644); + + /* Check for another level */ + + *pathptr++ = '/'; + if (*ptr == '/') + { + ptr++; + } + } + + /* Indicate we have created the audio dev path */ + + dev_audio_created = true; + } + + /* Now build the path for registration */ + + strcpy(path, devname); + if (devname[sizeof(devname)-1] != '/') + { + strcat(path, "/"); + } + strcat(path, name); + +#endif /* CONFIG_AUDIO_DEV_PATH=="/dev" */ + +#else /* CONFIG_AUDIO_CUSTOM_DEV_PATH */ + /* Create a /dev/audio directory. */ if (!dev_audio_created) @@ -485,6 +568,7 @@ int audio_register(FAR const char *name, FAR struct audio_lowerhalf_s *dev) strcpy(path, devname); strcat(path, "/"); strncat(path, name, AUDIO_MAX_DEVICE_PATH - 11); +#endif audvdbg("Registering %s\n", path); return register_driver(path, &g_audioops, 0666, upper); @@ -496,7 +580,7 @@ int audio_register(FAR const char *name, FAR struct audio_lowerhalf_s *dev) * Description: * Dequeues a previously enqueued Audio Pipeline Buffer. * - * 1. The upper half driver calls the enqueuebuffer method, providing the + * 1. The upper half driver calls the enqueuebuffer method, providing the * lower half driver with the ab_buffer to process. * 2. The lower half driver's enqueuebuffer will either processes the * buffer directly, or more likely add it to a queue for processing @@ -505,13 +589,14 @@ int audio_register(FAR const char *name, FAR struct audio_lowerhalf_s *dev) * ab_buffer, it will call this routine to indicated processing of the * buffer is complete. * 4. When this routine is called, it will check if any threads are waiting - * to enqueue additional buffers and "wake them up" for further + * to enqueue additional buffers and "wake them up" for further * processing. * * Input parameters: * handle - This is the handle that was provided to the lower-half * start() method. * apb - A pointer to the previsously enqueued ap_buffer_s + * status - Status of the dequeue operation * * Returned Value: * None @@ -521,14 +606,66 @@ int audio_register(FAR const char *name, FAR struct audio_lowerhalf_s *dev) * ****************************************************************************/ -void audio_dequeuebuffer(FAR void *handle, FAR struct ap_buffer_s *apb) +static inline void audio_dequeuebuffer(FAR struct audio_upperhalf_s *upper, + FAR struct ap_buffer_s *apb, uint16_t status) { - //FAR struct audio_upperhalf_s *upper = (FAR struct audio_upperhalf_s *)handle; - audllvdbg("Entry\n"); /* TODO: Implement the logic */ } +/**************************************************************************** + * Name: audio_callback + * + * Description: + * Provides a callback interface for lower-half drivers to call to the + * upper-half for buffer dequeueing, error reporting, etc. + * + * Input parameters: + * priv - Private context data owned by the upper-half + * reason - The reason code for the callback + * apb - A pointer to the previsously enqueued ap_buffer_s + * status - Status information associated with the callback + * + * Returned Value: + * None + * + * Assumptions: + * This function may be called from an interrupt handler. + * + ****************************************************************************/ + +static void audio_callback(FAR void *handle, uint16_t reason, + FAR struct ap_buffer_s *apb, uint16_t status) +{ + FAR struct audio_upperhalf_s *upper = (FAR struct audio_upperhalf_s *)handle; + + audllvdbg("Entry\n"); + + /* Perform operation based on reason code */ + + switch (reason) + { + case AUDIO_CALLBACK_DEQUEUE: + { + /* Call the dequeue routine */ + + audio_dequeuebuffer(upper, apb, status); + break; + } + + case AUDIO_CALLBACK_IOERR: + { + } + break; + + default: + { + auddbg("Unknown callback reason code %d\n", reason); + break; + } + } +} + #endif /* CONFIG_AUDIO */ diff --git a/nuttx/audio/buffer.c b/nuttx/audio/buffer.c index d6c6ac930..3906891f6 100644 --- a/nuttx/audio/buffer.c +++ b/nuttx/audio/buffer.c @@ -50,7 +50,7 @@ #include <debug.h> #include <nuttx/kmalloc.h> -#include <nuttx/audio.h> +#include <nuttx/audio/audio.h> #include <nuttx/usb/audio.h> #if defined(CONFIG_AUDIO) diff --git a/nuttx/audio/pcm.c b/nuttx/audio/pcm.c index 4f77c67c5..aeb1b7b64 100644 --- a/nuttx/audio/pcm.c +++ b/nuttx/audio/pcm.c @@ -50,7 +50,7 @@ #include <debug.h> #include <nuttx/kmalloc.h> -#include <nuttx/audio.h> +#include <nuttx/audio/audio.h> #if defined(CONFIG_AUDIO) && defined(CONFIG_AUDIO_FORMAT_PCM) diff --git a/nuttx/configs/mikroe-stm32f4/src/Makefile b/nuttx/configs/mikroe-stm32f4/src/Makefile index c166e1926..5ca1fe3ee 100644 --- a/nuttx/configs/mikroe-stm32f4/src/Makefile +++ b/nuttx/configs/mikroe-stm32f4/src/Makefile @@ -94,6 +94,10 @@ ifeq ($(CONFIG_LCD_MIO283QT2),y) CSRCS += up_mio283qt2.c endif +ifeq ($(CONFIG_VS1053),y) +CSRCS += up_vs1053.c +endif + COBJS = $(CSRCS:.c=$(OBJEXT)) SRCS = $(ASRCS) $(CSRCS) diff --git a/nuttx/configs/mikroe-stm32f4/src/mikroe-stm32f4-internal.h b/nuttx/configs/mikroe-stm32f4/src/mikroe-stm32f4-internal.h index d1a69547e..0f6894316 100644 --- a/nuttx/configs/mikroe-stm32f4/src/mikroe-stm32f4-internal.h +++ b/nuttx/configs/mikroe-stm32f4/src/mikroe-stm32f4-internal.h @@ -92,7 +92,9 @@ GPIO_OUTPUT_SET|GPIO_PORTD|GPIO_PIN3) #define GPIO_CS_FLASH (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz|\ GPIO_OUTPUT_SET|GPIO_PORTD|GPIO_PIN7) -#define GPIO_CS_MP3 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz|\ +#define GPIO_CS_MP3_DATA (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz|\ + GPIO_OUTPUT_SET|GPIO_PORTC|GPIO_PIN9) +#define GPIO_CS_MP3_CMD (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz|\ GPIO_OUTPUT_SET|GPIO_PORTC|GPIO_PIN8) #define GPIO_CS_EXP_SPI3 (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz|\ GPIO_OUTPUT_SET|GPIO_PORTD|GPIO_PIN0) @@ -182,6 +184,13 @@ #define GPIO_TP_XL (GPIO_ANALOG|GPIO_PORTB|GPIO_PIN1) +/* MP3 Codec control pins */ + +#define GPIO_VS1053_RST (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz|\ + GPIO_OUTPUT_SET|GPIO_PORTC|GPIO_PIN7) +#define GPIO_VS1053_DREQ (GPIO_INPUT|GPIO_SPEED_50MHz|GPIO_PORTC|GPIO_PIN6) + + /**************************************************************************************************** * Public Types ****************************************************************************************************/ @@ -258,5 +267,17 @@ void stm32_lcdinitialize(void); int up_lcdinitialize(void); #endif +/**************************************************************************************************** + * Name: up_vs1053initialize + * + * Description: + * Initialize the VS1053 Audio CODEC hardware. + * + ****************************************************************************************************/ + +#ifdef CONFIG_VS1053 +void up_vs1053initialize(FAR struct spi_dev_s *spi); +#endif + #endif /* __ASSEMBLY__ */ #endif /* __CONFIGS_MIKROE_STM32F4_SRC_MIKROE_STM32F4_INTERNAL_H */ diff --git a/nuttx/configs/mikroe-stm32f4/src/up_nsh.c b/nuttx/configs/mikroe-stm32f4/src/up_nsh.c index 648f69c64..366e4e8f6 100644 --- a/nuttx/configs/mikroe-stm32f4/src/up_nsh.c +++ b/nuttx/configs/mikroe-stm32f4/src/up_nsh.c @@ -64,7 +64,7 @@ #endif #ifdef CONFIG_AUDIO -# include "nuttx/audio.h" +# include "nuttx/audio/audio.h" #endif #include "stm32.h" @@ -182,9 +182,6 @@ int nsh_archinitialize(void) FAR struct spi_dev_s *spi; FAR struct mtd_dev_s *mtd; #endif -#ifdef CONFIG_AUDIO - FAR struct audio_lowerhalf_s *pVs1053; -#endif int ret; /* Configure SPI-based devices */ @@ -351,21 +348,13 @@ int nsh_archinitialize(void) #endif - /* Configure the Audio sub-system if enabled */ + /* Configure the Audio sub-system if enabled and bind it to SPI 3 */ #ifdef CONFIG_AUDIO - pVs1053 = vs1053_initialize(0); - if (pVs1053 == NULL) - { - message("nsh_archinitialize: Failed to initialize VS1053 Audio module\n"); - } - else - { - /* Bind the vs1053 to the audio upper-half driver */ - audio_register("mp30", pVs1053); - } + up_vs1053initialize(spi); + +#endif -#endif /* CONFIG_AUDIO */ return OK; } diff --git a/nuttx/configs/mikroe-stm32f4/src/up_spi.c b/nuttx/configs/mikroe-stm32f4/src/up_spi.c index 08fa89a9c..448ed966a 100644 --- a/nuttx/configs/mikroe-stm32f4/src/up_spi.c +++ b/nuttx/configs/mikroe-stm32f4/src/up_spi.c @@ -114,8 +114,10 @@ void weak_function stm32_spiinitialize(void) #endif #ifdef CONFIG_AUDIO_MP3_CODEC - (void)stm32_configgpio(GPIO_CS_MP3); /* MP3 codec chip select */ - stm32_gpiowrite(GPIO_CS_MP3, 1); /* Ensure the CS is inactive */ + (void)stm32_configgpio(GPIO_CS_MP3_DATA); /* MP3 codec chip select for DATA */ + (void)stm32_configgpio(GPIO_CS_MP3_CMD); /* MP3 codec chip select for CMD */ + stm32_gpiowrite(GPIO_CS_MP3_DATA, 1); /* Ensure the CS is inactive */ + stm32_gpiowrite(GPIO_CS_MP3_CMD, 1); /* Ensure the CS is inactive */ #endif /* Configure the EXP I/O cs for SPI3 */ @@ -172,11 +174,16 @@ void stm32_spi3select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool sele #endif #if defined(CONFIG_AUDIO_MP3_CODEC) - if (devid == SPIDEV_AUDIO) + if (devid == SPIDEV_AUDIO_DATA) { - stm32_gpiowrite(GPIO_CS_MP3, !selected); + stm32_gpiowrite(GPIO_CS_MP3_DATA, !selected); + } + else if (devid == SPIDEV_AUDIO_CTRL) + { + stm32_gpiowrite(GPIO_CS_MP3_CMD, !selected); } else + #endif /* Must be the expansion header device */ diff --git a/nuttx/configs/mikroe-stm32f4/src/up_vs1053.c b/nuttx/configs/mikroe-stm32f4/src/up_vs1053.c new file mode 100644 index 000000000..cc7e0f96d --- /dev/null +++ b/nuttx/configs/mikroe-stm32f4/src/up_vs1053.c @@ -0,0 +1,200 @@ +/**************************************************************************** + * configs/mikroe-stm32f4/src/up_vs1053.c + * + * Copyright (C) 2013 Ken Pettit. All rights reserved. + * Author: Ken Pettit <pettitkd@gmail.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdint.h> +#include <stdio.h> +#include <debug.h> + +#include <nuttx/spi.h> +#include <nuttx/audio/audio.h> +#include <nuttx/audio/vs1053.h> + +#include <arch/board/board.h> + +#include "chip.h" +#include "up_arch.h" +#include "mikroe-stm32f4-internal.h" + +#ifdef CONFIG_VS1053 + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* VS1053 is on SPI3 */ + +#ifndef CONFIG_STM32_SPI3 +# error "Need CONFIG_STM32_SPI3 in the configuration" +#endif + +/* SPI Assumptions **********************************************************/ + +#define VS1053_SPI_PORTNO 3 /* On SPI3 */ +#define VS1053_DEVNO 0 /* Only one VS1053 */ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct stm32_lower_s +{ + const struct vs1053_lower_s lower; /* Low-level MCU interface */ + xcpt_t handler; /* VS1053 interrupt handler */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int up_attach(FAR const struct vs1053_lower_s *lower, xcpt_t handler); +static void up_enable(FAR const struct vs1053_lower_s *lower); +static void up_disable(FAR const struct vs1053_lower_s *lower); +static void up_reset(FAR const struct vs1053_lower_s *lower, bool state); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* The VS1053 provides interrupts to the MCU via a GPIO pin. The + * following structure provides an MCU-independent mechanixm for controlling + * the VS1053 GPIO interrupt. + */ + +static struct stm32_lower_s g_vs1053lower = +{ + .lower = + { + .attach = up_attach, + .enable = up_enable, + .disable = up_disable, + .reset = up_reset + }, + .handler = NULL, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: struct vs1053_lower_s methods + ****************************************************************************/ + +static int up_attach(FAR const struct vs1053_lower_s *lower, xcpt_t handler) +{ + FAR struct stm32_lower_s *priv = (FAR struct stm32_lower_s *)lower; + + /* Just save the handler for use when the interrupt is enabled */ + + priv->handler = handler; + return OK; +} + +static void up_enable(FAR const struct vs1053_lower_s *lower) +{ + FAR struct stm32_lower_s *priv = (FAR struct stm32_lower_s *)lower; + + DEBUGASSERT(priv->handler); + (void)stm32_gpiosetevent(GPIO_VS1053_DREQ, false, true, true, priv->handler); +} + +static void up_disable(FAR const struct vs1053_lower_s *lower) +{ + (void)stm32_gpiosetevent(GPIO_VS1053_DREQ, false, true, true, NULL); +} + +static void up_reset(FAR const struct vs1053_lower_s *lower, bool state) +{ + stm32_gpiowrite(GPIO_VS1053_RST, state); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_netinitialize + ****************************************************************************/ + +void up_vs1053initialize(FAR struct spi_dev_s* spi) +{ + int ret; + int x; + char name[8]; + FAR struct audio_lowerhalf_s *pVs1053; + + /* Assumptions: + * 1) SPI pins were configured in up_spi.c early in the boot-up phase. + * 2) Clocking for the SPI1 peripheral was also provided earlier in boot-up. + */ + + /* Take VS1053 out of reset (active low)*/ + + (void)stm32_configgpio(GPIO_VS1053_RST); + (void)stm32_configgpio(GPIO_VS1053_DREQ); + + stm32_gpiowrite(GPIO_VS1053_RST, 0); + for (x = 0; x < 10000; x++); + stm32_gpiowrite(GPIO_VS1053_RST, 1); + + /* Bind the SPI port to the VS1053 driver */ + + pVs1053 = vs1053_initialize(spi, &g_vs1053lower.lower, VS1053_DEVNO); + if (ret < 0) + { + audlldbg("Failed to bind SPI port %d VS1053 device: %d\n", + VS1053_DEVNO, ret); + return; + } + + /* Now register the audio device */ + + sprintf(name, "mp3%d", VS1053_DEVNO); + ret = audio_register(name, pVs1053); + if (ret < 0) + { + auddbg("up_vs1053initialize: Failed to register VS1053 Audio device\n"); + } + + audllvdbg("Bound SPI port to VS1053 device %s\n", name); +} + +#endif /* CONFIG_VS1053 */ diff --git a/nuttx/configs/open1788/README.txt b/nuttx/configs/open1788/README.txt index 0dc559f02..c15985d16 100644 --- a/nuttx/configs/open1788/README.txt +++ b/nuttx/configs/open1788/README.txt @@ -120,7 +120,7 @@ FPU If you are using a toolchain other than the Atollic toolchain, then to use the FPU you will also have to modify the CFLAGS to enable compiler support for the ARMv7-M FPU. As of this writing, there are not many GCC toolchains that will support the - ARMv7-M FPU. + ARMv7-M FPU. As a minimum you will need to add CFLAG options to (1) enable hardware floating point code generation, and to (2) select the FPU implementation. You might try the same @@ -211,7 +211,7 @@ Using OpenOCD with the Olimex ARM-USB-OCD I have been using the Olimex ARM-USB-OCD debugger. OpenOCD requires a configuration file. I keep the one I used last here: - + configs/open1788/tools/open1788.cfg However, the "correct" configuration script to use with OpenOCD may @@ -240,7 +240,7 @@ Using OpenOCD with the Olimex ARM-USB-OCD NOTE: These files could also be located under /usr/share in some installations. They could be most anywhwere if you are using a windows version of OpenOCD. - + configs/open1788/tools/open1788.cfg This is simply openocd-usb.cfg, lpc1788.cfg, and lpc17xx.cfg concatenated into one file for convenience. Don't use it @@ -249,7 +249,7 @@ Using OpenOCD with the Olimex ARM-USB-OCD There is also a script on the tools/ directory that I use to start the OpenOCD daemon on my system called oocd.sh. That script will probably require some modifications to work in another environment: - + - Possibly the value of OPENOCD_PATH and TARGET_PATH - It assumes that the correct script to use is the one at configs/open1788/tools/open1788.cfg @@ -283,7 +283,7 @@ Using OpenOCD with the Olimex ARM-USB-OCD use the 'monitor' (or simply 'mon') command to invoke these sub- commands. These GDB commands will send comments to the OpenOCD monitor. Here are a couple that you will need to use: - + (gdb) monitor reset (gdb) monitor halt @@ -309,17 +309,17 @@ Using OpenOCD with the Olimex ARM-USB-OCD 3. I find that there are often undetected write failures when using the Olimex ARM-USB-OCD debugber and that if you start the program - with a bad FLASH failure, it will lock up OpenOCD. I usually + with a bad FLASH failure, it will lock up OpenOCD. I usually oad nuttx twice, restarting OpenOCD in between in order to assure good FLASH contents: - + (gdb) mon halt (gdb) load nuttx (gdb) mon reset Exit GDB, kill the OpenOCD server, recycle power on the board, restart the OpenOCD server and GDB, then: - + (gdb) mon halt (gdb) load nuttx (gdb) mon reset @@ -340,12 +340,12 @@ CONFIGURATION ============= ostest - ------ + ------ This configuration directory, performs a simple OS test using apps/examples/ostest. NOTES: - + 1. This configuration uses the mconf-based configuration tool. To change this configuration using that tool, you should: @@ -377,7 +377,7 @@ CONFIGURATION binaries (pass2) NOTES: - + 1. This configuration uses the mconf-based configuration tool. To change this configuration using that tool, you should: @@ -475,7 +475,7 @@ CONFIGURATION Configuration enables only the serial NSH interface. NOTES: - + 1. This configuration uses the mconf-based configuration tool. To change this configuration using that tool, you should: @@ -539,7 +539,7 @@ CONFIGURATION System Type: CONFIG_GPIO_IRQ=y : GPIO interrupt support CONFIG_LPC17_SSP1=y : Enable support for SSP1 - + Applicaton Configuration: CONFIG_EXAMPLES_TOUCHSCREEN=y : Enable the touchscreen built-int test CONFIG_EXAMPLES_TOUCHSCREEN_BUILTIN=y @@ -596,7 +596,7 @@ CONFIGURATION CONFIG_EXAMPLES_BUTTONS_NAME5="JOYSTICK_C" CONFIG_EXAMPLES_BUTTONS_NAME6="JOYSTICK_D" CONFIG_EXAMPLES_BUTTONS_NAME7="JOYSTICK_CTR" - + nxlines ------- Configures the graphics example located at examples/nsh. This @@ -605,7 +605,7 @@ CONFIGURATION panel. NOTES: - + 1. This configuration uses the mconf-based configuration tool. To change this configuration using that tool, you should: diff --git a/nuttx/drivers/audio/vs1053.c b/nuttx/drivers/audio/vs1053.c index 6f143acf9..b8aa7e41f 100644 --- a/nuttx/drivers/audio/vs1053.c +++ b/nuttx/drivers/audio/vs1053.c @@ -55,12 +55,19 @@ #include <nuttx/kmalloc.h> #include <nuttx/fs/fs.h> #include <nuttx/fs/ioctl.h> -#include <nuttx/audio.h> +#include <nuttx/audio/audio.h> +#include <nuttx/audio/vs1053.h> + +#include "vs1053.h" /**************************************************************************** * Private Definitions ****************************************************************************/ +#ifndef CONFIG_VS1053_SPIMODE +# define CONFIG_VS1053_SPIMODE SPIDEV_MODE0 +#endif + /**************************************************************************** * Private Types ****************************************************************************/ @@ -70,7 +77,7 @@ struct vs1053_struct_s FAR struct audio_lowerhalf_s lower; /* We derive the Audio lower half */ /* Our specific driver data goes here */ - int spidevice; /* Placeholder device data */ + FAR struct spi_dev_s *spi; /* Pointer to the SPI bus */ }; @@ -81,13 +88,16 @@ struct vs1053_struct_s static int vs1053_getcaps(FAR struct audio_lowerhalf_s *lower, int type, FAR struct audio_caps_s *pCaps); static int vs1053_configure(FAR struct audio_lowerhalf_s *lower, - FAR const struct audio_caps_s *pCaps); + FAR const struct audio_caps_s *pCaps, audio_callback_t upper, + FAR void *priv); static int vs1053_shutdown(FAR struct audio_lowerhalf_s *lower); -static int vs1053_start(FAR struct audio_lowerhalf_s *lower); +static int vs1053_start(FAR struct audio_lowerhalf_s *lower); static int vs1053_stop(FAR struct audio_lowerhalf_s *lower); -static int vs1053_enqueuebuffer(FAR struct audio_lowerhalf_s *lower, +static int vs1053_enqueuebuffer(FAR struct audio_lowerhalf_s *lower, FAR struct ap_buffer_s *apb); -static int vs1053_ioctl(FAR struct audio_lowerhalf_s *lower, int cmd, +static int vs1053_cancelbuffer(FAR struct audio_lowerhalf_s *lower, + FAR struct ap_buffer_s *apb); +static int vs1053_ioctl(FAR struct audio_lowerhalf_s *lower, int cmd, unsigned long arg); /**************************************************************************** @@ -102,6 +112,7 @@ static const struct audio_ops_s g_audioops = vs1053_start, /* start */ vs1053_stop, /* stop */ vs1053_enqueuebuffer, /* enqueue_buffer */ + vs1053_cancelbuffer, /* cancel_buffer */ vs1053_ioctl /* ioctl */ }; @@ -109,6 +120,73 @@ static const struct audio_ops_s g_audioops = * Private Functions ****************************************************************************/ +/************************************************************************************ + * Name: vs1053_spi_lock + ************************************************************************************/ + +static void vs1053_spi_lock(FAR struct spi_dev_s *dev) +{ + /* On SPI busses where there are multiple devices, it will be necessary to + * lock SPI to have exclusive access to the busses for a sequence of + * transfers. The bus should be locked before the chip is selected. + * + * This is a blocking call and will not return until we have exclusiv access to + * the SPI buss. We will retain that exclusive access until the bus is unlocked. + */ + + (void)SPI_LOCK(dev, true); + + /* After locking the SPI bus, the we also need call the setfrequency, setbits, and + * setmode methods to make sure that the SPI is properly configured for the device. + * If the SPI buss is being shared, then it may have been left in an incompatible + * state. + */ + + SPI_SETMODE(dev, CONFIG_VS1053_SPIMODE); + SPI_SETBITS(dev, 8); + (void)SPI_SETFREQUENCY(dev, 20000000); +} + +/************************************************************************************ + * Name: vs1053_spi_unlock + ************************************************************************************/ + +static inline void vs1053_spi_unlock(FAR struct spi_dev_s *dev) +{ + (void)SPI_LOCK(dev, false); +} + +/************************************************************************************ + * Name: vs1053_readreg - Read the specified 16-bit register from the + * VS1053 device. Caller must hold the SPI lock. + ************************************************************************************/ + +static uint16_t vs1053_readreg(FAR struct vs1053_struct_s *dev, uint16_t reg) +{ + uint16_t ret; + FAR struct spi_dev_s *spi = dev->spi; + + /* Select the AUDIO_CTRL device on the SPI bus */ + + SPI_SELECT(spi, SPIDEV_AUDIO_CTRL, true); + + /* Send the WRITE command followed by the address */ + + SPI_SEND(spi, VS1053_OPCODE_READ); + SPI_SEND(spi, reg); + + /* Now read the 16-bit value */ + + ret = SPI_SEND(spi, 0xFF) << 8; + ret |= SPI_SEND(spi, 0xFF); + + /* Deselect the CODEC */ + + SPI_SELECT(spi, SPIDEV_AUDIO_CTRL, false); + + return ret; +} + /**************************************************************************** * Name: vs1053_getcaps * @@ -126,15 +204,24 @@ static int vs1053_getcaps(FAR struct audio_lowerhalf_s *lower, int type, /**************************************************************************** * Name: vs1053_configure * - * Description: Configure the audio device for the specified mode of + * Description: Configure the audio device for the specified mode of * operation. * ****************************************************************************/ static int vs1053_configure(FAR struct audio_lowerhalf_s *lower, - FAR const struct audio_caps_s *pCaps) + FAR const struct audio_caps_s *pCaps, audio_callback_t upper, + FAR void *priv) { audvdbg("Entry\n"); + + /* Save the binding to the upper level operations and private data */ + + lower->upper = upper; + lower->priv = priv; + + /* Now process the configure operation */ + return OK; } @@ -163,7 +250,7 @@ static int vs1053_shutdown(FAR struct audio_lowerhalf_s *lower) static int vs1053_start(FAR struct audio_lowerhalf_s *lower) { //struct vs1053_struct_s *dev = (struct vs1053_struct_s *) lower; - + /* Perform the start */ return OK; @@ -191,7 +278,20 @@ static int vs1053_stop(FAR struct audio_lowerhalf_s *lower) * ****************************************************************************/ -static int vs1053_enqueuebuffer(FAR struct audio_lowerhalf_s *lower, +static int vs1053_enqueuebuffer(FAR struct audio_lowerhalf_s *lower, + FAR struct ap_buffer_s *apb ) +{ + return OK; +} + +/**************************************************************************** + * Name: vs1053_cancelbuffer + * + * Description: Called when an enqueued buffer is being cancelled. + * + ****************************************************************************/ + +static int vs1053_cancelbuffer(FAR struct audio_lowerhalf_s *lower, FAR struct ap_buffer_s *apb ) { return OK; @@ -204,7 +304,7 @@ static int vs1053_enqueuebuffer(FAR struct audio_lowerhalf_s *lower, * ****************************************************************************/ -static int vs1053_ioctl(FAR struct audio_lowerhalf_s *lower, int cmd, +static int vs1053_ioctl(FAR struct audio_lowerhalf_s *lower, int cmd, unsigned long arg) { return OK; @@ -226,18 +326,19 @@ static int vs1053_ioctl(FAR struct audio_lowerhalf_s *lower, int cmd, * ****************************************************************************/ -struct audio_lowerhalf_s *vs1053_initialize(int spidevice) +struct audio_lowerhalf_s *vs1053_initialize(FAR struct spi_dev_s *spi, + FAR const struct vs1053_lower_s *lower, + unsigned int devno) { struct vs1053_struct_s *dev; + uint16_t status; + uint8_t id; /* Sanity check */ -#ifdef CONFIG_DEBUG - if (spidevice < 0 || spidevice > 3) - { - return NULL; - } -#endif + DEBUGASSERT(spi != NULL); + DEBUGASSERT(lower != NULL); + DEBUGASSERT(lower->reset != NULL); /* Allocate a VS1053 device structure */ @@ -247,10 +348,32 @@ struct audio_lowerhalf_s *vs1053_initialize(int spidevice) /* Initialize the SMART device structure */ dev->lower.ops = &g_audioops; + dev->lower.upper = NULL; + dev->lower.priv = NULL; /* Save our specific device data */ - dev->spidevice = spidevice; + dev->spi = spi; + + /* Reset the VS1053 chip */ + + lower->reset(lower, false); + up_udelay(4000); + lower->reset(lower, true); + + /* Do device detection to validate the chip is there. + * We have to hold the SPI lock during reads / writes. + */ + + vs1053_spi_lock(spi); + status = vs1053_readreg(dev, VS1053_SCI_STATUS); + vs1053_spi_unlock(spi); + + id = (status & VS1053_SS_VER) >> VS1053_VER_SHIFT; + if (id != VS1053_VER_VS1053) + { + auddbg("Unexpected VER bits: 0x%0X\n", id); + } } return &dev->lower; diff --git a/nuttx/drivers/audio/vs1053.h b/nuttx/drivers/audio/vs1053.h new file mode 100644 index 000000000..5cdd167ae --- /dev/null +++ b/nuttx/drivers/audio/vs1053.h @@ -0,0 +1,222 @@ +/**************************************************************************** + * drivers/audio/vs1053.h + * + * Copyright (C) 2013 Ken Pettit. All rights reserved. + * Author: Ken Pettit <pettitkd@gmail.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __DRIVERS_AUDIO_VS1053_H +#define __DRIVERS_AUDIO_VS1053_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#include <nuttx/compiler.h> + +#include <nuttx/fs/ioctl.h> + +#ifdef CONFIG_AUDIO + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* SCI Instruction Opcodes **************************************************/ + +#define VS1053_OPCODE_READ 3 +#define VS1053_OPCODE_WRITE 2 + +/* SCI Registers on the SPI bus *********************************************/ + +#define VS1053_SCI_MODE 0x00 +#define VS1053_SCI_STATUS 0x01 +#define VS1053_SCI_BASE 0x02 +#define VS1053_SCI_CLOCKF 0x03 +#define VS1053_SCI_DECODE_TIME 0x04 +#define VS1053_SCI_AUDATA 0x05 +#define VS1053_SCI_WRAM 0x06 +#define VS1053_SCI_WRAMADDR 0x07 +#define VS1053_SCI_HDAT0 0x08 +#define VS1053_SCI_HDAT1 0x09 +#define VS1053_SCI_AIADDR 0x0A +#define VS1053_SCI_VOL 0x0B +#define VS1053_SCI_AICTRL0 0x0C +#define VS1053_SCI_AICTRL1 0x0E +#define VS1053_SCI_AICTRL2 0x0E +#define VS1053_SCI_AICTRL3 0x0F + +/* MODE register bit definitions ********************************************/ + +#define VS1053_SM_DIFF 0x0001 +#define VS1053_SM_LAYER12 0x0002 +#define VS1053_SM_RESET 0x0004 +#define VS1053_SM_CANCEL 0x0008 +#define VS1053_SM_EARSPEAKER_LO 0x0010 +#define VS1053_SM_TESTS 0x0020 +#define VS1053_SM_STREAM 0x0040 +#define VS1053_SM_EARSPEAKER_HI 0x0080 +#define VS1053_SM_DACT 0x0100 +#define VS1053_SM_SDIORD 0x0200 +#define VS1053_SM_SDISHARE 0x0400 +#define VS1053_SM_SDINEW 0x0800 +#define VS1053_SM_ADPCM 0x1000 +#define VS1053_SM_LINE1 0x4000 +#define VS1053_SM_CLK_RANGE 0x8000 + +/* STATUS register bit definitions ****************************************/ + +#define VS1053_SS_DO_NOT_JUMP 0x8000 +#define VS1053_SS_SWING 0x7000 +#define VS1053_SS_VCM_OVERLOAD 0x0800 +#define VS1053_SS_VCM_DISABLE 0x0400 +#define VS1053_SS_VER 0x00F0 +#define VS1053_SS_APDOWN2 0x0008 +#define VS1053_SS_APDOWN1 0x0004 +#define VS1053_SS_AD_CLOCK 0x0002 +#define VS1053_SS_REFERENCE_SEL 0x0001 + +#define VS1053_VER_SHIFT 4 +#define VS1053_VER_VS1001 0 +#define VS1053_VER_VS1011 1 +#define VS1053_VER_VS1002 2 +#define VS1053_VER_VS1003 3 +#define VS1053_VER_VS1053 4 +#define VS1053_VER_VS1033 5 +#define VS1053_VER_VS1063 6 +#define VS1053_VER_VS1103 7 + +/* BASE register bit definitions ******************************************/ + +#define VS1053_ST_AMPLITUDE 0xF000 +#define VS1053_ST_FREQLIMIT 0x0F00 +#define VS1053_SB_AMPLITUDE 0x00F0 +#define VS1053_SB_FREQLIMIT 0x000F + +/* CLOCKF register bit definitions ****************************************/ + +#define VS1053_SC_MULT 0xE000 +#define VS1053_SC_ADD 0x1800 +#define VS1053_SC_FREQ 0x07FF + +#define VS1053_SC_MULT_XTALIx10 0 +#define VS1053_SC_MULT_XTALIx20 1 +#define VS1053_SC_MULT_XTALIx25 2 +#define VS1053_SC_MULT_XTALIx30 3 +#define VS1053_SC_MULT_XTALIx35 4 +#define VS1053_SC_MULT_XTALIx40 5 +#define VS1053_SC_MULT_XTALIx45 6 +#define VS1053_SC_MULT_XTALIx50 7 + +#define VS1053_SC_ADD_NONE 0 +#define VS1053_SC_ADD_XTALIx10 1 +#define VS1053_SC_ADD_XTALIx15 2 +#define VS1053_SC_ADD_XTALIx20 3 + +/* WRAM Addresses **********************************************************/ + +#define VS1053_XRAM_BASE 0x1800 /* X data RAM */ +#define VS1053_XRAM_SIZE 256 + +#define VS1053_YRAM_BASE 0x5800 /* Y data RAM */ +#define VS1053_YRAM_SIZE 256 + +#define VS1053_IRAM_BASE 0x8040 /* Instruction RAM */ +#define VS1053_IRAM_SIZE 0x460 + +#define VS1053_IO_BASE 0xC000 +#define VS1053_IO_SIZE 0x4000 + +/* HDAT1 register values *************************************************/ + +#define VS1053_HDAT1_WAV 0x7665 /* "ve" (as in Wave) */ +#define VS1053_HDAT1_ADTS 0x4154 /* "AT" */ +#define VS1053_HDAT1_ADIF 0x4144 /* "AD" */ +#define VS1053_HDAT1_AAC 0x4D34 /* "M4" */ +#define VS1053_HDAT1_WMA 0x574D /* "WM" */ +#define VS1053_HDAT1_MIDI 0x4D54 /* "MT" */ +#define VS1053_HDAT1_OGG 0x4F67 /* "Og" */ + +/* MP3 special definitions for HDAT1 / 0 */ + +#define VS1053_HDAT1_MP3_SYNC 0xFFE0 /* Stream valid */ +#define VS1053_HDAT1_MP3_ID 0x0018 /* MPG id */ +#define VS1053_HDAT1_MP3_LAYER 0x0006 +#define VS1053_HDAT1_MP3_PROTECT 0x0001 /* CRC Protect bit */ +#define VS1053_HDAT0_MP3_BITRATE 0xF000 +#define VS1053_HDAT0_MP3_SAMPRATE 0x0C00 +#define VS1053_HDAT0_MP3_PAD 0x0200 +#define VS1053_HDAT0_MP3_PRIVATE 0x0100 +#define VS1053_HDAT0_MP3_MODE 0x00C0 +#define VS1053_HDAT0_MP3_EXTENSION 0x0030 +#define VS1053_HDAT0_MP3_COPYRIGHT 0x0008 +#define VS1053_HDAT0_MP3_ORIGINAL 0x0004 +#define VS1053_HDAT0_MP3_EMPHASIS 0x0003 + +#define VS1053_MP3_ID_SHIFT 7 +#define VS1053_MP3_ID_MPEG1 3 +#define VS1053_MP3_ID_MPEG2 2 +#define VS1053_MP3_ID_MPEG25a 1 +#define VS1053_MP3_ID_MPEG25b 0 + +#define VS1053_MP3_LAYER_SHIFT 1 +#define VS1053_MP3_LAYER_I 3 +#define VS1053_MP3_LAYER_II 2 +#define VS1053_MP3_LAYER_III 1 + +#define VS1053_MP3_CRC_NONE 1 +#define VS1053_MP3_CRC_PROTECT 0 + +#define VS1053_MP3_PAD_SHIFT 9 +#define VS1053_MP3_PAD_ADDITIONAL 1 +#define VS1053_MP3_PAD_NORMAL 0 + +#define VS1053_MP3_MODE_SHIFT 6 +#define VS1053_MP3_MODE_MONO 3 +#define VS1053_MP3_MODE_DUAL_CH 2 +#define VS1053_MP3_MODE_JSTEREO 1 +#define VS1053_MP3_MODE_STEREO 0 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#endif /* CONFIG_AUDIO */ +#endif /* __DRIVERS_AUDIO_VS1053_H */ diff --git a/nuttx/include/nuttx/audio.h b/nuttx/include/nuttx/audio/audio.h index 1e6464adc..72b8cb573 100644 --- a/nuttx/include/nuttx/audio.h +++ b/nuttx/include/nuttx/audio/audio.h @@ -1,5 +1,5 @@ /**************************************************************************** - * include/nuttx/audio.h + * include/nuttx/audio/audio.h * * Copyright (C) 2013 Ken Pettit. All rights reserved. * Author: Ken Pettit <pettitkd@gmail.com> @@ -33,8 +33,8 @@ * ****************************************************************************/ -#ifndef __INCLUDE_NUTTX_AUDIO_H -#define __INCLUDE_NUTTX_AUDIO_H +#ifndef __INCLUDE_NUTTX_AUDIO_AUDIO_H +#define __INCLUDE_NUTTX_AUDIO_AUDIO_H /* For the purposes of this driver, an Audio device is any device that * generates, records, mixes, or otherwise modifies audio data in any format, @@ -56,6 +56,7 @@ #include <nuttx/compiler.h> #include <nuttx/fs/ioctl.h> +#include <nuttx/spi.h> #ifdef CONFIG_AUDIO @@ -165,6 +166,12 @@ #define AUDIO_RATE_192K 0x08 #define AUDIO_RATE_320K 0x09 +/* Audio Callback Reasons ***************************************************/ + +#define AUDIO_CALLBACK_UNDEF 0x00 +#define AUDIO_CALLBACK_DEQUEUE 0x01 +#define AUDIO_CALLBACK_IOERR 0x02 + /* Audio Pipeline Buffer (AP Buffer) flags **********************************/ #define AUDIO_ABP_ALIGNMENT 0x000F /* Mask to define buffer alignment */ @@ -226,6 +233,11 @@ struct ap_buffer_s uint8_t samp[0]; /* Offset of the first sample */ } packed_struct; +/* Typedef for lower-level to upper-level callback for buffer dequeuing */ + +typedef CODE void (*audio_callback_t)(FAR void *priv, uint16_t reason, + FAR struct ap_buffer_s *apb, uint16_t status); + /* This structure is a set a callback functions used to call from the upper- * half, generic Audo driver into lower-half, platform-specific logic that * supports the low-level functionality. @@ -245,15 +257,17 @@ struct audio_ops_s CODE int (*getcaps)(FAR struct audio_lowerhalf_s *dev, int type, FAR struct audio_caps_s *pCaps); - /* This method is called to configure the driver for a specific mode of + /* This method is called to bind the lower-level driver to the upper-level + * driver and to configure the driver for a specific mode of * operation defined by the parameters selected in supplied device caps - * strucure. The lower-level device should perform any initialization + * structure. The lower-level device should perform any initialization * needed to prepare for operations in the specified mode. It should not, * however, process any audio data until the start method is called. */ CODE int (*configure)(FAR struct audio_lowerhalf_s *dev, - FAR const struct audio_caps_s *pCaps); + FAR const struct audio_caps_s *pCaps, + audio_callback_t upper, FAR void *priv); /* This method is called when the driver is closed. The lower half driver * should stop processing audio data, including terminating any active @@ -280,7 +294,7 @@ struct audio_ops_s /* Enqueue a buffer for processing. This is a non-blocking enqueue operation. * If the lower-half driver's buffer queue is full, then it should return an - * error code of -ENOMEM, and the upper-half driver can decide to either block + j* error code of -ENOMEM, and the upper-half driver can decide to either block * the calling thread or deal with it in a non-blocking manner. * For each call to enqueuebuffer, the lower-half driver must call @@ -293,6 +307,11 @@ struct audio_ops_s CODE int (*enqueuebuffer)(FAR struct audio_lowerhalf_s *dev, FAR struct ap_buffer_s *apb); + /* Cancel a previously enqueued buffer. */ + + CODE int (*cancelbuffer)(FAR struct audio_lowerhalf_s *dev, + FAR struct ap_buffer_s *apb); + /* Lower-half logic may support platform-specific ioctl commands */ CODE int (*ioctl)(FAR struct audio_lowerhalf_s *dev, @@ -319,6 +338,16 @@ struct audio_lowerhalf_s FAR const struct audio_ops_s *ops; + /* The bind data to the upper-half driver used for callbacks of dequeuing + * buffer, reporting asynchronous event, reporting errors, etc. + */ + + FAR audio_callback_t upper; + + /* The private opaque pointer to be passed to upper-layer during callbacks */ + + FAR void *priv; + /* The custom Audio device state structure may include additional fields * after the pointer to the Audio callback structure. */ @@ -435,28 +464,10 @@ EXTERN void apb_reference(FAR struct ap_buffer_s *apb); * Platform-Dependent "Lower-Half" Audio Driver Interfaces ****************************************************************************/ -/**************************************************************************** - * Name: vs1053_initialize - * - * Description: - * This function initializes the driver for the VS1053 codec chip - * - * Input parameters: - * spi - This is a placeholder for now. Actual init parameters will be - * determined once the audio interface is "finalized". - * - * Returned Value: - * Zero on success; a negated errno value on failure. - * - ****************************************************************************/ -#ifdef CONFIG_VS1053 -EXTERN FAR struct audio_lowerhalf_s *vs1053_initialize(int spidevice); -#endif - #undef EXTERN #ifdef __cplusplus } #endif #endif /* CONFIG_AUDIO */ -#endif /* __INCLUDE_NUTTX_AUDIO_H */ +#endif /* __INCLUDE_NUTTX_AUDIO_AUDIO_H */ diff --git a/nuttx/include/nuttx/audio/vs1053.h b/nuttx/include/nuttx/audio/vs1053.h new file mode 100644 index 000000000..5b791c023 --- /dev/null +++ b/nuttx/include/nuttx/audio/vs1053.h @@ -0,0 +1,122 @@ +/**************************************************************************** + * include/nuttx/audio/vs1053.h + * + * Copyright (C) 2013 Ken Pettit. All rights reserved. + * Author: Ken Pettit <pettitkd@gmail.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_NET_VS1053_H +#define __INCLUDE_NUTTX_NET_VS1053_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <stdint.h> +#include <stdbool.h> + +#include <nuttx/irq.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* VS1053 Configuration Settings: + * + * CONFIG_VS1053 - Enabled VS1053 support + * CONFIG_VS1053_SPIMODE - Controls the SPI mode + */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* The VS1053 provides Data Request (DREQ) interrupts to the MCU via a GPIO + * pin and also has a chip reset GPIO. The following structure provides an + * MCU-independent mechanism for controlling the VS1053 GPIOs. + */ + +struct vs1053_lower_s +{ + int (*attach)(FAR const struct vs1053_lower_s *lower, xcpt_t handler); + void (*enable)(FAR const struct vs1053_lower_s *lower); + void (*disable)(FAR const struct vs1053_lower_s *lower); + void (*reset)(FAR const struct vs1053_lower_s *lower, bool state); +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Function: vs1053_initialize + * + * Description: + * Initialize the VS1053 driver. This will perform a chip reset of the + * device as part of initialization. + * + * Parameters: + * spi - A reference to the platform's SPI driver for the VS1053 + * lower - The MCU-specific interrupt used to control low-level MCU + * functions (i.e., VS1053 GPIO interrupts). + * devno - If more than one VS1053 is supported, then this is the + * zero based number that identifies the VS1053; + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +struct spi_dev_s; /* see nuttx/spi.h */ +struct audio_lowerhalf_s; /* see nutt/audio.h */ +EXTERN FAR struct audio_lowerhalf_s *vs1053_initialize(FAR struct spi_dev_s *spi, + FAR const struct vs1053_lower_s *lower, + unsigned int devno); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_NET_VS1053_H */ diff --git a/nuttx/include/nuttx/spi.h b/nuttx/include/nuttx/spi.h index 7eb7fb908..4816e7d8b 100644 --- a/nuttx/include/nuttx/spi.h +++ b/nuttx/include/nuttx/spi.h @@ -358,7 +358,8 @@ enum spi_dev_e SPIDEV_TOUCHSCREEN, /* Select SPI touchscreen device */ SPIDEV_EXPANDER, /* Select SPI I/O expander device */ SPIDEV_MUX, /* Select SPI multiplexer device */ - SPIDEV_AUDIO /* Select SPI audio codec device */ + SPIDEV_AUDIO_DATA, /* Select SPI audio codec device data port */ + SPIDEV_AUDIO_CTRL, /* Select SPI audio codec device control port */ }; /* Certain SPI devices may required differnt clocking modes */ |