AVR32 UC3 Audio Decoder Over USB
投稿人:Convergence Promotions LLC
2011-07-08
Atmel provides detailed source code for an MP3 decoder that runs on its AVR32 UC3 MCU. This article explains in detail how to configure and use it.
This article will help the reader to use the AVR32® UC3 Audio Decoder over USB software. This software includes a software MP3 decoder, a file system, and USB host mass storage class support.
For more information about the AVR32 architecture, please refer to the appropriate documents available at http://www.atmel.com/avr32.
License
The MP3 audio decoder (MAD) is distributed under the terms of the GPL. The JPEG decoder (IJG) license can be found in the file /SERVICES/PICTURES/JPG/IJG/license.txt. The memory manager (dlmalloc) license can be found in the file /SERVICES/MEMORY/MEMORY_MANAGER/DLMALLOC/license.txt.
Requirements
The software referenced in this article requires several components:
- A computer running Microsoft® Windows® 2000/XP/Vista or Linux®
- AVR32 Studio and the GNU toolchain (GCC) or IAR Embedded Workbench® for the AVR32 compiler
- A JTAGICE mkII or AVROne! debugger
Overview
Today, embedded MP3 decoders are everywhere for consumers listening to audio content on mobile devices.
MP3
MPEG-1 Audio Layer III, more commonly referred to as MP3, is a digital audio encoding format using a form of lossy data compression. Several bit rates are specified in the MPEG-1 Audio Layer III standard: 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, and 320 Kbps. The available sampling frequencies are 32, 44.1, and 48 KHz, and a sample rate of 44.1 KHz is almost always used. 128 Kbps bitrate files are slowly being replaced with higher bitrates such as 192 Kbps, with some being encoded up to the MP3 maximum of 320 Kbps.
A tag, in a compressed audio file, is a section of the file which contains metadata such as the title, artist, album, track number, or other information about the file's contents.
The chosen MP3 decoder here is MAD (libmad), a high-quality MPEG audio decoder. It currently supports MPEG-1 and the MPEG-2 extension to lower sampling frequencies, as well as the so-called MPEG 2.5 format. All three audio layers (Layer I, Layer II, and Layer III) are fully implemented. MAD does not yet support MPEG-2 multichannel audio (although it should be backward compatible with such streams).
Block diagram
Figure 1 shows the UC3 interfacing to the USB stick, and outputting the audio stream from the key to the external DAC. The user can control the player using a keypad, or running a customizable Human Machine Interface (HMI).
Figure 1: Block diagram.
Software architecture
Figure 2 shows the basic software architecture of the application.
Figure 2: Software architecture.
The application does not require any operating system to run. The main() function is in charge of calling the software tasks (using a scheduler) that make audio decoding, HMI, and USB management possible. There are five tasks:
- The Communication Task contains the HMI of the application. This task holds the real intelligence of the user application and interfaces directly with the Audio Interface (AI). This is the task that the user should modify for their own application.
- Audio Interface Task: This task handles dynamic support for any newly plugged-in device types. For example, if a new device, using another class than the mass storage class, is plugged in, and if this class is supported by the application, then this task will tell the Audio Interface to link the Audio Interface API to a low level API that supports this class. All the mechanisms in place to dynamically link an API to this abstract API are located in the file: /SERVICES/AUDIO/AUDIO_PLAYER/audio_interface.[c|h]. In this application, only the USB mass storage class is implemented. Therefore, this function is not used.
- The last task is a macro used for feature tasks. In the MP3 audio player using USB, the modules involved will be the MP3 decoder, the USB stack, and the host mass storage task:
- The MP3 Codec Task: This task is in charge of Audio Decoding management.
- The USB Task: This task handles the USB stack and events.
- The Host Mass Storage Task: This task will check for newly connected devices and initialize them using the USB mass storage class.
while (TRUE)
{
ai_task();
com_task();
task();
}
The Audio Interface can also support iPod audio decoding through the USB audio class. Please refer to the application note AVR32730: AVR32 UC3 iPod Support Over USB for more information.{
}
Audio Interface API
The audio player is a generic audio player interface and is designed to support multiple audio formats besides MP3.
Overview
The Audio Interface manages disk navigation, audio navigation, and audio control. Thus, the user does not have to directly interface with the file system and audio control APIs. This greatly simplifies the software architecture.
The Audio Interface can be used in two ways:
- Using asynchronous functions, the results or effects of which may not be produced in a single iteration, usually leads to the use of state machines in the user firmware (since one must wait for the completion of a command before launching a new one), and has the advantage of reducing the risk of audio underrun. Asynchronous functions always have the "ai_async" prefix.
Note that only one asynchronous function can be used at a time. - Using synchronous functions, which are executed immediately, this drastically simplifies the user firmware architecture (no use of state machines since the synchronous AI functions are immediately executed), but may produce audio underruns since the execution time of these functions may be too long. Synchronous functions just have the "ai_" prefix.
- ai_async_nav_drive_nb() in the asynchronous interface
- ai_nav_drive_nb() in the synchronous interface
Audio Interface (AI) architecture
The AI commands to interface the audio player are divided into three categories (See Figure 3):
- Disk navigation (Disk Nav) to browse into the tree architectures of the USB device
- Audio navigation (Audio Nav) to manage a list of playable songs
- Audio control (Audio CTRL) to control the audio stream (such as play, pause, and fast forward)
Figure 3: Audio player navigators overview.
Disk Navigator: "Browse into the tree architectures of the mass storage device"
The Disk Navigator is similar to a file explorer. It is used to navigate in the tree architectures of the connected USB device. It will hide all files whose extension differs from *.mp3, *.pls, *.smp, or *.m3u. The file extension filtering is automatically updated according to the modules selected (such as MP3 and playlists).
The Disk Navigator is totally independent from the Audio Navigator.
The commands associated with this module are used to navigate into the disks/directories, and to synchronize the selected file/folder with the Audio Nav module. This synchronization is made with two commands: ai_nav_getplayfile and ai_audio_nav_playfile. See the "Disk Navigation" section later in this article for a complete list of commands.
Audio Navigator: "Manage a list of playable songs"
The Audio Navigator deals with a list of files. This list is defined once an ai_audio_nav_playfile command is executed. This command sets the list of files to be played according to the current selection in the Disk Navigator and to the Audio Navigator ai_audio_nav_expmode_set option.
When the ai_audio_nav_playfile command is executed:
- If the Disk Navigator is currently pointing to a playlist (*.m3u), then only the files of this playlist will be included in the Audio Navigator file list.
- If the Disk Navigator is currently pointing to a disk or a file, then the file list will depend on the audio explorer mode (set by the ai_audio_nav_expmode_set command) (See Table 1).
- If the Disk Navigator is currently pointing to a folder, the Audio Navigator will not enter into it. It will look for the first file that is in the current directory and build its file list according to the previous rules.
- If the Disk Navigator is not pointing to any files or folders (which is the case after a mount or a goto) when a directory or a playlist is selected, then it will select the first file of the file list.
Explorer Mode | Behavior |
AUDIO_EXPLORER_MODE_DISKS | Builds a file list off all playable songs of all disks, and starts playing from the selected file. |
AUDIO_EXPLORER_MODE_DISK | Builds a file list off all playable songs of the current disk only, and starts playing from the selected file. |
AUDIO_EXPLORER_MODE_DIRONLY | Builds a file list of all playable songs that are contained in the current directory, and starts playing from the selected file. Sub directories are ignored. |
AUDIO_EXPLORER_MODE_DIRSUB | Builds a file list off all playable songs that are contained in the current directory and its sub-directories, and starts playing from the selected file. |
Table 1: ai_audio_nav_expmode_set command behavior.
Note that the playing order can be changed at compilation time by enabling a define. This is fully explained in the "Example 3 — Change the playing order" section later in this article.
Once the file list is set, two main commands are available to navigate into it:
- ai_audio_nav_next (select next file).
- ai_audio_nav_previous (select previous file).
To synchronize the Disk Navigator with the Audio Navigator, i.e., to make the Disk Navigator select the file played by the Audio Navigator, the command ai_nav_getplayfile can be used. See the "Audio Navigation" section later in this article for a complete list of commands.
Audio Control: "control the audio stream
(play/pause/fast forward/...)"
This module controls the audio stream of the selected file (selected by the Audio Navigator). Commands like play, pause, stop, fast forward, and fast rewind are available. See the "Audio Control" section later in this article for a complete list of commands (See Table 2).
Limitations
Speed
Speed navigation (such as file browsing) in directories may be affected if:
- A high-bitrate file is played at the same time.
- Directories have many files.
- The playlist includes many files.
The exploration is based on a selector displacement. The file list is the list of the files in the current directory according to the extension filter (i.e., .mp3, .m3u, .pls, and .smp).
The file list:
- Is updated when you exit or enter a directory or a disk
- Starts with the directories then the files
- Is sorted in the creation order
Command Name | Input | Output | Description | |
Return | Extra Result | |||
ai_get_product_id | – | Product ID | – | Returns the product identifier (USB PID) of the connected device (if available). |
ai_get_vendor_id | – | Vendor ID | – | Returns the vendor identifier (USB VID) of the connected device (if available). |
ai_get_serial_number | – | Length of the serial number in bytes | Serial number | Returns the serial number of the connected device (if available). |
ai_nav_drive_nb | – | Number of drive | – | Returns the serial number of disk available. |
ai_nav_drive_set | Drive Number | True or false | – | Selects the disk but does not mount it: (0 for drive 0, 1 for drive 1...). Returns false in case of error. |
ai_nav_drive_get | – | Drive Number | – | Returns the selected disk number. |
ai_nav_drive_mount | – | True or false | – | Mounts the selected disk. Returns false in case of error. |
ai_nav_drive_total_space | – | Capacity of the drive | – | Returns the total space, in bytes and available on the device. |
ai_nav_drive_free_space | – | Free space on the drive | – | Returns the free space, in bytes, available on the device. |
ai_nav_dir_root | – | True or false | – | Initializes the file list on the root directory. Return false in case of error. |
ai_nav_dir_cd | – | True or false | – | Enters in the current directory selected in file list. Return false in case of error. |
ai_nav_dir_gotoparent | – | True or False | – | Exits current directory and goes to the parent's directory. Then selects the folder from which it just exits, rather than selecting the first file of the parent directory. This simplifies navigation since the user firmware does not have to memorize the information. Returns false in case of error. |
ai_nav_file_isdir | – | True or false | – | Returns true if the selected file is a directory, otherwise returns false. |
ai_nav_file_goto | Position in the list | True or false | – | Goes to a position in file list (0 for position 0, 1 for position 1...). Returns false in case of error. |
ai_nav_file_pos | – | File position | – | Returns the file position of the selected file in the current directory. Returns FS_NO_SEL if no file is selected. |
ai_nav_file_nb | – | Number of audio files | – | Returns the number of audio files in the file list. Audio files are all the files which extensions matches *.mp3 or *.wma (it depends on the file format supported). There is a specific command for playlist files, see below. |
ai_nav_dir_nb | – | Number of directories | – | Returns the number of directories in the file list. |
ai_nav_playlist_nb | – | Number of playlists | – | Returns the number of playlists in the file list. The playlists are all the files matching with the extension *m3u, *.pls and *.smp. |
ai_nav_dir_name | – | Length of the string in bytes | UNICODE name | Returns the name of the current directory. |
ai_nav_file_name | – | Length of the string in bytes | UNICODE name | Returns the name of the selected file. |
ai_nav_file_info_type | – | File type | – | Returns the type of the audio file selected. |
ai_nav_file_info_version | – | Version number | – | Returns the version of the metadata storage method used for the selected audio file if available, otherwise, returns 0. |
ai_nav_file_info_title | – | Length of the string in bytes | UNICODE title | Returns the title of the selected audio file if available, otherwise, returns an empty string. |
ai_nav_file_info_artist | – | Length of the string in bytes | UNICODE artist | Returns the artist's name of the selected audio file if available, otherwise, returns an empty string. |
ai_nav_file_info_album | – | Length of the string in bytes | UNICODE album | Returns the album's name of the selected audio file if available, otherwise, returns an empty string. |
ai_nav_file_info_year | – | Year | – | Returns the year of the selected audio file if available, otherwise, returns 0. |
ai_nav_file_info_track | – | Length of the string in bytes | UNICODE info | Returns the track information of the selected audio file if available, otherwise, returns an empty string. |
ai_nav_file_info_genre | – | Length of the string in bytes | UNICODE genre | Returns genre of the selected audio file if available, otherwise, returns an empty string. |
ai_nav_file_info_duration | – | Duration of the track | – | Returns the total time of the selected audio file in milliseconds if available, otherwise, returns 0. |
ai_nav_file_image | Max image size | Image size | -True or false -A pointer on the image data | Returns information and a pointer on the bitmap of the embedded cover art of the selected audio file. Returns false in case of error. |
ai_nav_getoplayfile | – | True or false | – | Selects the file selected by the navigator. This command is the only link between these two navigators. Returns false in case of error. |
Table 2: Disk Navigator commands.
Audio navigation
This navigator sets the list of files to be played. It can be seen as a playlist. Before accessing this navigator, an ai_audio_nav_playfile command must be issued.
Command Name | Input | Output | Description | |
Return | Extra Result | |||
ai_audio_nav_playfile | — | True or false | — | This command sets the audio file list according to the current mode of the audio navigator and plays (or sets to pause) the file selected in the disk navigator. In other words, it synchronizes the audio navigator with the disk navigator and plays (or sets to pause) the selected file from the disk navigator. Note that this command returns immediately and does not wait until the current track is completely played. This command does not change the current options (repeat/random/expmode). It is the opposite of the command ai_nav_getplayfile. Returns false in case of error. |
ai_audio_context_save | — | Structure context | — | — True or false — The length of the structure in bytes |
ai_audio_context_restore | Structure Context | True or false | — | Restores an audio context (eventually restart playing). |
ai_audio_nav_next | — | True or false | — | Jump to next audio file available in the list. The next song file is chosen according to the current options (repeat/random/mode). |
ai_audio_nav_previous | — | True or false | — | Jumps to previous audio file available in the list. The next song file is chosen according to the current options (repeat/random/mode). |
ai_audio_nav_eof_occur | — | True or false | — | This routine must be called once a track ends. It will choose, according to the options (repeat/random/expmode), the next file to play. |
ai_audio_nav_nb | — | Number of audio files present in the list | — | Returns the number of audio files present in the list. |
ai_audio_nav_getpos | — | File position | — | Returns the file position of the selected file in the list. |
ai_audio_nav_setpos | File position | True or false | — | Goes to a position in the list. |
ai_audio_nav_repeat_get | — | Ai_repeat_mode | — | Returns the current repeat mode (no repeat, repeat single, repeat folder, repeat all). |
ai_audio_nav_repeat_set | Ai_repeat_mode | — | — | Sets the current repeat mode (no repeat single, repeat folder, repeat all). |
ai_audio_nav_shuffle_get | — | Ai_shuffle_mode | — | Returns the current shuffle mode (no shuffle, shuffle folder, shuffle all). |
ai_audio_nav_shuffle_set | Ai_shuffle_mode | — | — | Sets the current shuffle mode (no shuffle, shuffle folder, shuffle all). |
ai_audio_nav_expmode_get | — | Ai_explorer_mode | — | Returns the current explorer mode (all disks, one disk, directory only, directory + sub directories). |
ai_audio_nav_expmode_set | Ai_explorer_mode | — | — | Sets the current explorer mode (all disks, one disk, directory only, directory + sub directories). This mode cannot be changed while an audio file is being played. |
ai_audio_nav_getname | — | Length of the string in bytes | UNICODE name | Returns the name of selected file. |
ai_audio_nav_file_info_type | — | File type | — | Returns the type of the audio file selected. |
ai_audio_nav_file_info_version | — | Version number | — | Returns the version of the metadata storage method used for the selected audio file if available, otherwise, returns 0. |
ai_audio_nav_file_info_title | — | Length of the string in bytes | UNICODE title | Returns the title of the selected audio file if available, otherwise, returns and empty string. |
ai_audio_nav_file_artist | — | Length of the string in bytes | UNICODE artist | Returns the artist's name of the selected audio file if available, otherwise, returns an empty string. |
ai_audio_nav_file_info_album | — | Length of string in bytes | UNICODE album | Returns the albums name of the selected audio file if available, otherwise, returns an empty string. |
ai_audio_nav_file_info_year | — | Year | — | Returns the year of the selected audio file if available, otherwise, returns 0. |
ai_audio_nav_file_info_track | — | Length of the string in bytes | UNICODE info | Returns the track information of the selected audio file if available, otherwise, returns an empty string. |
ai_audio_nav_file_info_genre | — | Length of the string in bytes | UNICODE genre | Returns the genre of the selected audio file if available, otherwise, returns an empty string. |
ai_audio_nav_file_info_duration | — | Duration of the track | — | Returns the total time of the selected audio file in milliseconds if available, otherwise, returns 0. |
ai_audio_nav_file_info_image | Max image size | Image size | —True or false — A pointer on the image data | Returns information and a pointer on a bitmap of the embedded cover art of the selected audio file. Returns false in case of error. |
Table 3: Audio Navigator commands.
Modes used by the interface
Ai_repeat_mode defines the repeat mode:
— | AUDIO_REPEAT_OFF: no repeat |
— | AUDIO_REPEAT_TRACK: repeat the current track |
— | AUDIO_REPEAT_FOLDER: repeat the current folder |
— | AUDIO_REPEAT_ALL: repeat the list of files |
Ai_shuffle_mode defines the shuffle/random mode:
— | AUDIO_SHUFFLE_OFF: no shuffle |
— | AUDIO_SHUFFLE_FOLDER: shuffle into the current folder |
— | AUDIO_SHUFFLE_ALL: shuffle into the list of files |
Audio Control
The audio controller is used to control the audio stream of the audio file selected by the Audio Navigator.
Command Name | Input | Output | Description | |
Return | Extra Result | |||
ai_audio_ctrl_stop | — | True or false | — | Stops the audio. |
ai_audio_ctrl_resume | — | True or false | — | Plays or resumes play after an ai_audio_ctrl_pause or an ai_audio_ctrl_stop command. |
ai_audio_ctrl_pause | — | True or false | — | Pauses the audio. |
ai_audio_ctrl_time | — | Elapsed time | — | Returns the elapsed time of the audio track being played. |
ai_audio_ctrl_status | — | Status | — | Returns the status of the audio controller (stop, play, pause, a new audio file is being played, the current folder has changed). |
ai_audio_ctrl_ffw | Skip time | True or false | — | Fast forwards the audio until the skip time has been reached. Then, it will continue to play the rest of the audio file. The skip time passed in parameter is in second. |
ai_audio_ctrl_frw | Skip time | True or false | — | Fast rewinds the audio until the skip time has been reached. Then, it will set the audio player in play mode. The skip time passed in parameter is in second. |
ai_audio_ctrl_start_ffw | — | True or false | — | Sets the audio player into fast forward mode. Function not implemented yet. |
ai_audio_ctrl_start_frw | — | True or false | — | Sets the audio player into fast rewind mode. Function not implemented yet. |
ai_audio_stop_ffw_frw | — | True or false | — | Stops fast forwarding/rewinding and set the audio player into the previous mode (play or resume). Function not yet implemented. |
Table 4: Audio Control commands.
Using asynchronous or synchronous API
Using synchronous functions is straightforward. Once finished, synchronous functions return, with or without a result. Using asynchronous functions is more complicated; they may not produce the requested task in a single shot. Thus, these functions need some other functions to operate properly:
- void ai_async_cmd_task (void): This function is the entry point of all asynchronous commands. It must be called to execute the current state of the internal state machine of the current asynchronous function.
- Bool is_ai_async_cmd_finished (void): This function returns TRUE if the last command is finished.
- U8 ai_async_cmd_out_status (void): Returns the status of the last executed command (CMD_DONE, CMD_EXECUTING or CMD_ERROR).
- U32 ai_async_cmd_out_u32 (void): If the last executed command should return a 32-bit result or less, this function will return this value.
- U64 ai_async_cmd_out_u64 (void): If the last executed command should return a 64-bit result, this function will return this value.
- 16 ai_async_cmd_out_SizeArrayU8 (void): If the last executed command should return an extra result (e.g., a song name), this function returns the size in bytes of the extra result (no size limit).
- U8 ai_async_cmd_out_PtrArrayU8 (void): Returns a pointer to the extra result (assuming that the last executed command returns an extra result). This pointer can be freed by the application with the ai_async_cmd_out_free_ArrayU8() function.
- void ai_async_cmd_out_free_ArrayU8 (void): This function may be called to free the allocated buffer that holds the extra result. Note that the Audio Interface will automatically do this before executing a new command that needs extra results. This ensures that the application will not have memory leakage. Allowing the application calling this function to free the extra results sooner and improve allocated memory usage. Figure 4 shows the flow of the asynchronous function use.
Figure 4: Asynchronous function flow.
Examples
The code for the next a three examples can be found in the following directories:
Let's take this disk as disk number 0 for the system.
Example 1 - Play "file1.mp3"
Command Order | Command Name |
0 | ai_nav_drive_nb(): returns 1 disk. |
1 | ai_nav_drive_set(0): selects the disk 0. |
2 | ai_nav_drive_mount(): mounts the select disk 0. |
3 | ai_nav_file_goto(0): goes to file position 0 |
4 | ai_nav_file_name(): returns the name dir1 |
5 | ai_nav_file_isdir(): returns true, the current file is a directory. |
6 | ai_nav_file_goto(1): goes to file position 1 |
7 | ai_nav_file_name(): returns the name dir2 |
8 | ai_nav_file_goto(2): goes to file position 2 |
9 | ai_nav_file_name():returns the name file1.mp3 |
10 | ai_audio_nav_playfile(): selects the file selected by the file nagivator (file1.mp3) |
11 | ai_audio_ctrl_resume(): plays the selected file. |
12 | Wait for 10 seconds to listen to the beginning of the playback. |
13 | ai_nav_file_goto(3): goes to file position 3 |
14 | ai_nav_file_name(): returns the name file2.wma |
Table 5: Example: Play "file1.mp3."
Example 2 — Play while browsing
Command Order | Command Name |
0 | ai_nav_drive_nb(): returns 1 disk. |
1 | ai_nav_drive_set(0): selects the disk 0. |
2 | ai_nav_drive_mount(): mounts the select disk 0. |
3 | ai_audio_nav_playfile(): selects a file in the audio navigator. By default it will seek inside the directories to play the first file which is "file5.wma" in our case. |
4 | ai_audio_ctrl_resume (): plays the selected file. |
5 | ai_nav_getplayfile(): synchronizes the disk navigator with the audio navigator. Now the disk navigator is pointing on the "file5.wma" file. |
6 | ai_nav_file_nb()+ai_nav_dir_nb()+ai_nav_playlist_nb(): gets the total number of entries (files+folder+playlist) in the current directory (dir3). |
7 | ai_nav_file_goto(0): goes to the file position 0 |
8 | ai_nav_file_name(): returns the name "file5.wma". (Notice the difference with Table 5 - step #4) |
9 | ai_nav_file_goto(1): goes to file position 1 |
10 | ai_nav_file_name(): returns the name "file6.mp3" |
11 | ai_audio_ctrl_stop(): stops the audio |
Table 6: Example: Play while browsing.
Example 3 — Change the playing order
The playing order can be changed at compilation time by enabling the NAV_AUTO_FILE_IN_FIRST define (see the "Project Configuration" section later in this article).
Command Order | Command Name |
0 | ai_nav_drive_nb(): returns 1 disk. |
1 | ai_nav_drive_set(0): selects the disk 0. |
2 | ai_nav_drive_moutn(): mounts the select disk 0. |
3 | ai_audio_nav_playfile(): selects a file in the audio player. |
4 | ai_audio_ctrl_resume(): plays the selected file. |
Table 7: Playfile sequence.
If the NAV_AUTO_FILE_IN_FIRST define is not set, the sequence will play audio files in the order shown in Table 8.
Command Order | Command Name | Parent directory path |
0 | file5.wma | /dir1/dir3/ |
1 | file6.mp3 | /dir1/dir3/ |
2 | file4.mp3 | /dir1/ |
3 | file7.mp3 | /dir2/ |
4 | file1.mp3 | / |
5 | file2.wma | / |
6 | file3.wma | / |
Table 8: Playfile sequence with NAV_AUTO_FILE_IN_FIRST undefined.
If this define is set, the sequence will play audio files starting with files on the root, as shown in Table 9.
Command Order | Command Name | Parent directory path |
0 | file1.mp3 | / |
1 | file2.wma | / |
2 | file3.wma | / |
3 | file4.mp3 | /dir1/ |
4 | file5.wma | /dir1/dir3/ |
5 | file5.mp3 | /dir1/dir3/ |
6 | file7.mp3 | /dir2/ |
Table 9: Playfile sequence with NAV_AUTO_FILE_IN_FIRST defined.
Source code architecture
Package
AUDIO-PLAYER-<board(s)>-<feature(s)>-<version>.zip contains projects for GCC (or AVR32 Studio) and IAR.
The default hardware configuration of the project is to run on Atmel® AVR32 UC3 Evaluation Kits, although any board can be used (refer to the "Board Definition Files" section later in this article).
Documentation
For full source code documentation, please refer to the auto-generated Doxygen source code documentation found in:
- /APPLICATIONS/AUDIO-PLAYER/readme.html
The IAR project is located in:
- APPLICATIONS/AUDIO-PLAYER/<part>-<board>-vfeature(s)>/IAR/
- /APPLICATIONS/AUDIO-PLAYER/<part>-<board>-<feature(s)>/GCC/
Implementation details
This section describes the code implementation of the MP3 audio player running on the EVK1105. Other available packages are similar, so you will find useful information here that applies to every project configuration.
Main()
The main() function of the program is located in the file:
- //APPLICATIONS/AUDIO-PLAYER/main.c
- Initialize audio output — refer to the "Audio Rendering Interface" section later in this article.
- Do the clock configuration.
- Call the USB Task — refer to the "USB" section later in this article.
- Call the USB Host Mass Storage Task. This task will check for newly connected devices and initialize them using the USB mass storage protocol.
- Call the Communication Task (HMI) — refer to the "HMI Communication Task Example" section later in this article.
- Call the Decoder Task to perform MP3 decoding — refer to the following section "MP3 Decoder."
- ./main.c: Contains the main() function.
- ./com_task.c,h: HMI core. See the "HMI Communication Task Example" section later in this article for more details.
- ./USER_INTERFACE/CONTROLLER/joystick_controller.c: HMI using a joystick interface as a controller.
- ./USER_INTERFACE/GUI/et024006dhu_gui.c: HMI using an LCD screen as a display.
- ./codec_mp3_task.c: Handles the MP3 decoding task.
- ./CONF/*.h and ./<part>-<board>-<features>/conf_audio_player.h: Configuration file for audio, communication interface, memory and navigation explorer. Please refer to the "Project Configuration" section later in this article for more information on the configuration files.
The MP3 decoder source files are located in:
- /SERVICES/AUDIO/MP3/LIBMAD/: AVR32 port of LibMAD MP3 decoder.
ID3 is supported up to version 2.4. The ID3 reader source is located in:
- /SERVICES/AUDIO/MP3/ID3/reader_id3.c,h.
The Audio Interface API is located in:
- /SERVICES/AUDIO/AUDIO_PLAYER/audio_interface.h
- /SERVICES/AUDIO/AUDIO_PLAYER/AI_USB_MS/
- ./ai_usb_ms.c,h: Mass Storage Audio interface.
- ./ai_usb_ms_mp3_support.c,h: Adds support to the MP3 file format in the audio interface.
- ./host_mass_storage_task.c,h: USB host mass storage task.
HMI communication task example
The included firmware implements an HMI example using a joystick and an SPI-driven LCD (source code is located under /APPLICATIONS/AUDIO-PLAYER-MASS-STORAGE/USER_INTERFACE/).
All the HMI is based on a pair of files, com_task.[c|h], which implement all mechanisms used to communicate between the internal APIs of the audio player and the user's HMI. An abstraction layer is used to easily attach all kinds of controller and graphical user interfaces to this communication task. This has been done to easily port the application to another board.
Controller
The controller is the module that makes the link between the driver and the abstraction layer, and is used to ensure compatibility with the communication task. It is based mainly on two API groups: "setup" and "events." All the APIs are defined in the file /APPLICATIONS/AUDIO- PLAYER/USER_INTERFACE/CONTROLLER/controller.h.
The function controller_init is used to initialize the controller. It may or may not be used, depending on the controller implementation.
All the other functions are Boolean functions, returning TRUE if an event has been raised or FALSE otherwise. Their names are explicit and follow the following naming convention:
Bool controller_<view>_<event>(void);
where <view> corresponds to the current view when the event should be taken into account. If no value is set for this field, the event is applied to all views.
The <event> is a short name describing the current event to which the function applies.
This example uses a joystick controller. The source code relative to this module is available in the file /APPLICATIONS/AUDIO-PLAYER/USER_INTERFACE/CONTROLLER/joystick_controller.c.
Graphical user interface
This module is used to display the high level audio player data to the user. It acts as a display and, when combined with the controller, it provides the user full control of the application.
This module is similar to the controller in terms of API groups.
The initialization function is called gui_init and includes all the parameters and frequencies needed to initialize the display.
This function is called at every occurrence of the main loop, at which point it resets the parameter flags which indicate parts of the view that need to be updated. Resetting these flags enables the GUI module to update the display asynchronously without having to update every component at once.
The example provides a graphical LCD display module that implements both a navigation and a playback view. All the code is based on the files /APPLICATIONS/AUDIO-PLAYER/USER_INTERFACE/GUI/[et024006dhu_gui.c|sdram_loader.c].
AT32UC3A drivers
The firmware uses the AVR32 UC3 driver library available in:
- //UTILS/LIBS/DRIVERS/AT32UC3A/.
USB
The USB low level driver is located in:
- /DRIVERS/USB/.
- /SERVICES/USB/CLASS/MASS_STORAGE/.
The FAT12/16/32 files are located in the directory /SERVICES/FAT/.
Board definition files
The application is designed to run on Atmel Evaluation Kits. All projects are configured with the following define: BOARD=EVKxxxx. The EVKxxxx definition can be found in the /BOARDS/EVKxxxx directory.
Board customization
- For an IAR project, open the project options (Project —> Options), choose the "C/C++ Compiler," then "Preprocessor." Modify the "BOARD=EVKxxxx" definition by "BOARD=USER_BOARD."
- For GCC, just modify in the "config.mk" file (/APPLICATIONS/AUDIO-PLAYER/--/GCC/) the DEFS definition with "-D BOARD=USER_BOARD."
- For AVR32 Studio, open the project properties (Project —>Properties), go in the "C/C++ build," then "Settings," "tool settings" and "Symbols." Modify the "BOARD=EVKxxxx" definition by "BOARD=USER_BOARD."
Audio rendering interface
The audio DAC mixer source code is located in /SERVICES/AUDIO/AUDIO_MIXER/audio_mixer.c,h.
I2S using the SSC module
The /COMPONENTS/AUDIO/CODEC/TLV320AIC23B/ directory contains the driver for the external DAC TLV320AIC23B.
The UC3 communicates with the TLV320AIC23B with the Two Wire Interface (TWI). The UC3 is the TWI master.
The AVR32 SSC module generates I2S frames using internal DMA (PDCA) to free CPU cycles for audio decoding.
Each time a new song is played, the SSC module is configured corresponding to the sample rate of the new song. The SSC clocks are composed of a bit clock and a frame sync:
- The bit clock is the clock used to transmit a bit from the audio stream. For a 44.1 KHz sample rate, the bit clock will be 44,100 x 2 (stereo) x 16 (bits per channel), i.e., 1.411 MHz.
- The frame sync is equal to the sample rate frequency, i.e., 44.1 KHz, taking the same example.
The SSC clock divider in the CMR register is given by:
The real frequency sample rate outputted by the SSC is given by:
Note: NumberChannel = 2, BitsPerSamples = 16, FPBA = 62.0928 MHz.
The music interval in semitones is:
Sample Rate Set Point (Hz) | Actual Sample Rate (Hz) | Relative Error (%) | Music Interval (semitones) |
8000 | 8018 | 0.23 | 0.04 |
11025 | 11025 | 0.00 | 0.00 |
16000 | 15095 | -0.59 | -0.10 |
22050 | 22050 | 0.00 | 0.00 |
32000 | 32340 | 1.06 | 0.18 |
44100 | 44100 | 0.00 | 0.00 |
48000 | 48510 | 1.06 | 0.18 |
Table 10: Sample rate with SSC module.
For further information, please refer to the application note AVR32788: AVR®32 How to use the SSC in I2S mode. ABDAC
The ABDAC driver is located in /DRIVERS/ABDAC.
The external amplifier driver (TPA6 13 0A) is located in /COMPONENTS/AUDIO/AMP/TPA6130A.
The AVR32 ABDAC module uses the internal DMA (PDCA) to free CPU cycles for audio decoding.
To get accurate audio frequency samples, the two external 12 MHz (OSC1) and 11.2896 MHz (OSC0) oscillators are used to source (directly or through a PLL) the ABDAC generic clock.
Sample Rate Set Point (Hz) | ABDAC Generic clock input frequency | Actual Sample Rate (Hz) | Relative Error (%) | Music Interval (semitones) |
8000 | PLL0 | 8085 | 1.06 | 0.18 |
11025 | OSC1 | 11025 | 0.00 | 0.00 |
16000 | PLL1 | 15625 | -2.34 | -0.41 |
22050 | OSC1 | 22050 | 0.00 | 0.00 |
32000 | PLL1 | 31250 | -2.34 | -0.41 |
44100 | OSC1 | 44100 | 0.00 | 0.00 |
48000 | PLL1 | 46875 | -2.34 | -0.41 |
Table 11: Sample rate with ABDAC module.
The PLL0 output frequency is 62.0928 MHz. The PLL1 output frequency is 48 MHz (used for USB).
When used, the ABDAC generic clock divider is given by:
Refer to /DRIVERS/ABDAC/abdac.c for the configuration of the ABDAC generic clock.
SDRAM loader
Graphical data, such as images, consumes a lot of space in RAM and flash which could be used by the application instead. Because of that, the images used by the audio player application's GUI are stored in DataFlash and are loaded to SDRAM upon startup. The reason for having the data in the SDRAM, rather than in flash, is the speed improvement which leads to faster updates of the display with new content.
The SDRAM loader module uses a memory manager to manage the SDRAM memory space. This memory manager can also be used in the application to allocate memory from SDRAM, instead of the internal SRAM.
The following sections give a short introduction to the parts involved in the SDRAM loader module.
The SDRAM loader source code is located in /APPLICATIONS/AUDIO-PLAYER/USER_INTERFACE_GUI/sdram_loader.c,h.
DataFlash
The DataFlash is formatted with a FAT16 file system, and it currently contains graphical data used by the audio player application in the GUI implementation. The graphical data is stored as BMP files and the format is RGB565. This can be used directly on the display when swapped from little endian to big endian. Other BMP formats are currently not implemented but this could be extended, if needed.
The FAT file system makes it easy for developers to upgrade the content with new files or even use it for other applications such as a web server. An upgrade of the content can be done by using a mass storage example application.
The BMP pictures used in the application are stored in the /PICTURES directory.
To customize the GUI, the bitmap files can be updated and must be saved to the Windows bitmap image format using 16-bit R5 G6 B5 encoding. This can be done using GIMP, the GNU Image Manipulation Program (see http://www.gimp.org/).
Loading process
The SDRAM loader consists of two files, sdram_loader.c and sdram_loader.h, in the directory APPLICATIONS/AUDIO-PLAYER/ USER_INTERFACE/GUI. In these files, the images that should be loaded to SDRAM and how they should be converted are specified. A configuration that loads three images to SDRAM could look like this:
typedef struct { | |
const wchar_t *name; | |
void *start_addr; | |
} ram_file_t; | |
… | |
#define STARTUP_IMAGE 0 | |
#define DISK_NAV_IMAGE 1 | |
#define AUDIO_PLAYER_IMAGE 2 | |
#define NUMBER_OF_IMAGES 13 | |
ram_file_t ram_files[NUMBER_OF_IMAGES] = { | |
{ .name = L"/AVR32_start_320x240_RGB565.bmp"}, | |
{ .name = L"/disk_nav_320x240_RGB565.bmp"}, | |
{ .name = L"/audio_player.bmp"} | |
}; |
The ram_files array is used throughout the GUI to get access to the image data. In order to load other data than RGB565 BMP data to SDRAM, the module needs to be modified.
The SDRAM loader module is called once during the initialization of the graphical user interface. When called, it initializes the SDRAM interface and reads the raw image data from specified BMP files into SDRAM. To get the raw image data, the BMP header must be read to get the image size and the offset of the data in the file. The copy process also does a conversion from little endian to the big endian data ordering, thus the final image data can be dumped directly into the display buffer.
A single call to the SDRAM module is enough to do the initialization and load process:
void load_sdram_data(int hsb_hz);
The sole parameter is the HSB frequency in hertz, which is needed to initialize the SDRAM timings. The load_sdram_data function is called starting from main in the following order:
main() —> com_task() —> gui_init() —>sdram_load_data()
SDRAM memory management
The images could be placed at specified locations in SDRAM, making memory management unneeded, but it is often better to do memory management to remove the task of keeping track of the data in memory from the developer.
The audio player uses a separate memory manager to manage SDRAM memory (this memory manager can also replace the default memory manager in the Newlib library if needed).
The source files of the memory manager are located in /SERVICES/MEMORY/MEMORY_MANAGER/DLMALLOC/ and the additional configuration of it is /APPLICATIONS/AUDIO-PLAYER/CONF/conf_dlmalloc.h.
The memory manager is initialized in the SDRAM loader module and it is configured to use the whole SDRAM memory. After the initialization, memory can be allocated from the SDRAM with the mspace_malloc call. Memory from the internal SRAM can be allocated with the default malloc call.
JPEG decoder
The JPEG decoder is used for MP3 cover art file support.
The source code of the IJG JPEG decoder is located under /SERVICES/PICTURES/JPG/IJG/. Documentation for the library can be found in /SERVICES/PICTURES/JPG/IJG/libjpeg.doc and an overview is located in the README file.
The IJG license text can be found in /SERVICES/PICTURES/JPG/IJG/license.txt.
The JPEG decoder application source files are located under /APPLICATIONS/AUDIO-PLAYER/JPG/. This is a layer that handles the data input and output of the JPEG library. It also handles the error handling to jump out of the library in case of a critical error. Since the JPEG decoding is done in SDRAM, the memory management backend of the library, which normally would be included in the library itself, is located here. The memory management backend is modified to use SDRAM with the DLMALLOC memory manager (in /SERVICES/MEMORY/MEMORY_MANAGER/DLMALLOC/) instead of the standard malloc implementation.
Project configuration
There are two different configuration files. The one related to the audio player itself, located under /APPLICATIONS/AUDIOPLAYER/<part>-<board>-<feature(s)>/conf_audio_player.h, is mostly a high level configuration file, but can be customized to support certain configurations or enable/disable audio player features. The rest of the configuration files are located under the /APPLICATIONS/AUDIO-PLAYER/CONF/ directory and should be modified to change, separately, the audio player's module configurations.
Configuration files are not linked to IAR, GCC, or AVR32 Studio projects. The user can alter any of them, then rebuild the entire project in order to reflect the new configuration.
High level configuration file: /APPLICATIONS/AUDIO-PLAYER/<part>-<board>- <feature(s)>conf_audio_player.h
- DEFAULT_DACS specifies the default audio DAC used for the audio output. Three values are possible: AUDIO_MIXER_DAC_AIC23B for the I2S interface, AUDIO_MIXER_DAC_ABDAC for the internal DAC (ABDAC module), and AUDIO_MIXER_DAC_PWM_DAC to use PWM channels (an external low-pass filter is required).
- E_AUDIO_PLAYER_BUFFERIZATION, set to "ENABLED" to support the navigation while playing feature, will use extra memory to buffer decoded samples in order to prevent audio blips while the user navigates in the disk architecture, for example. The memory address and size can be configured in the file "conf_buff_player.h." Note that using the audio sample bufferization will not ensure that every audio blip will be covered. It will always depend on the speed of the USB device connected, its file system, and the operations requested. The default buffer size is set to 128 Kbytes.
- SUPPORT_MP3, SUPPORT_PLAYLISTS, SUPPORT_EMBEDDED_COVER_ARTS is a set of defines which can be enabled or disabled to reduce audio player features. Note that the use of the embedded cover art requires RAM in order to decode embedded JPEG pictures. Therefore, an external memory is needed to handle this feature.
conf_access.h – This file contains the possible external configuration of the memory access control. It configures the abstract layer between the memory and the application, and specifies the commands used in order to access the memory. For example, this file will define the functions to be called for SD/MMC memory access.
conf_audio_interface.h – A set of configuration flags to enable/disable internal features of the audio player.
conf_audio_mixer.h – Configures all parameters relative to the audio DACs. This file is made to support multiple configurations, and can be easily upgraded to handle new DACs.
conf_buff_player.h – Defines the starting address and the size of the memory used to bufferize audio samples (if the feature is enabled).
conf_dmalloc.h – Configuration of malloc/free functions.
conf_explorer.h – It defines the configuration used by the FAT file system. The configuration is also applied to the playlist handler and the file navigation. The main parameters are:
- NAV_AUTO_FILE_IN_FIRST: Must be defined in order to play first the files at the root of a directory instead of the ones inside the subdirectories.
- FS_NAV_AUTOMATIC_NBFILE: This flag can be set to DISABLE in order to speed up the response of the ai_audio_nav_playfile command. On the other hand, the three commands ai_audio_nav_getpos, ai_audio_nav_getpos, and ai_audio_nav_nb will not be available anymore. It will also affect the use of the explorer modes, if different from "all disks" and "one disk."
conf_pwm_dac.h — Configuration of the PWM DAC (which PWM channel is used, which pins are concerned).
conf_tlv320aic23b.h — Configuration of the external I2S DAC (which pins and which configuration interface are used).
conf_usb.h — Configuration file used for the USB.
conf_version.h — Internal version of the firmware.
Compiling the application
The following steps show you how to build the embedded firmware according to your environment.
If you are using AVR32 Studio:
- Please refer to the application note AVR32769: How to Compile the standalone AVR32 Software Framework in AVR32 Studio V2.
- Open a shell, go to the /APPLICATIONS/AUDIO-PLAYER/<partf>-<board>-<feature(s)>/GCC/ directory and type: make rebuild program run.
- Open IAR and load the associated IAR project of this application (located in the directory /APPLICATIONS/AUDIO-PLAYER/<part>-<board>-<feature(s)>/IAR/).
- Press the "Debug" button at the top right of the IAR interface.
- Click on the "Go" button in the "Debug" menu or press F5.
Q: What is the maximum number of playlist links supported?
A: The file system supports up to 65,535 links inside a playlist.
Q: What are the supported text formats?
A: The file system supports the ASCII, UTF8 and UNICODE (UTF16LE & UTF16BE) text formats.
Q: How are the directories and files sorted inside the disk?
A: The logical structure is the same as an explorer view. Directory and files are sorted using their creation order.
Q: Which file systems are supported?
A: FAT12/16/32.
Q: What is the maximum number of files supported in a directory?
A: There is no limitation in the firmware for the supported number of files and directories. The only limitation is due to the FAT file system:
- for FAT12/16 root directory only: up to 256 files (short names).
- or FAT12/16/32 up to 65,535 files (short names) per directory.
A: The default application is using external SDRAM to support all features. This application can run with 64 kbytes of RAM (internal size on AT32UC3A0512) by disabling the audio bufferization and the cover art support. Audio blips will be present if the user tries to navigate in the disk while a track is played. The SDRAM loader also uses external SDRAM memory for graphical data.
Q: What kind of license applies to the software?
A: Atmel provides the audio decoder software library free of charge. But some digital audio formats, including MP3 and WMA, contain technology that is patented, and a license for these patents must be obtained before the library can be used.
免责声明:各个作者和/或论坛参与者在本网站发表的观点、看法和意见不代表 DigiKey 的观点、看法和意见,也不代表 DigiKey 官方政策。