mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
5683281b5d
Apparently, those functions have never been used. Otherwise this obvious bug wouldn't have sailed unnoticed for so long.
778 lines
31 KiB
C
778 lines
31 KiB
C
/*
|
|
* Copyright 2019 Marian Buschsieweke
|
|
*
|
|
* This file is subject to the terms and conditions of the GNU Lesser
|
|
* General Public License v2.1. See the file LICENSE in the top level
|
|
* directory for more details.
|
|
*/
|
|
|
|
/**
|
|
* @defgroup drivers_dfplayer DFPlayer Mini MP3 Player
|
|
* @ingroup drivers_multimedia
|
|
* @brief Driver for the DFPlayer Mini MP3 Player
|
|
*
|
|
* The DFPlayer Mini is a super cheap MP3 Player that can be controlled via
|
|
* UART. It can play files from SD card, USB storage devices and NOR flash.
|
|
* It has an integrated 3W amplifier that can be used to build a standalone
|
|
* mono speaker. Alternatively a stereo output can be used that can be
|
|
* directly connected to headphones, but needs a dedicated amplifier for
|
|
* connecting to passive speakers.
|
|
*
|
|
* ![DFPlayer pinout](https://camo.githubusercontent.com/fd6ed047e8e3ced124b32051ddfff2df9e8afe47/68747470733a2f2f63646e2e73686f706966792e636f6d2f732f66696c65732f312f313530392f313633382f66696c65732f4d50335f706c617965725f6d6f64756c655f70696e6f75745f6469616772616d2e706e67)
|
|
*
|
|
* File System Setup
|
|
* =================
|
|
*
|
|
* The SD card or USB storage devices needs to be formatted as FAT32 and the
|
|
* MP3 files have to be stored using one of the following naming schemes, if
|
|
* selecting the files efficiently is required:
|
|
*
|
|
* Numbered File Inside Numbered Folder Naming Scheme
|
|
* --------------------------------------------------
|
|
*
|
|
* The MP3 files have to be named with three leading decimal digits (e.g.
|
|
* `001.mp3` or `042 - foo bar.mp3`) and must be placed in in folders named with
|
|
* two decimal digits (e.g. `01` or `99`). The folder name numbers must be in
|
|
* the range 1-99 and the file name numbers in the range 1-255. Playback of
|
|
* these files can be started using the function @ref dfplayer_play_file .
|
|
*
|
|
* Examples of valid paths:
|
|
*
|
|
* - `01/001.mp3`
|
|
* - `19/249 - Nothing Else Matters.mp3`
|
|
*
|
|
* Examples of ***INVALID*** paths:
|
|
*
|
|
* - `01 - Yngwie Malmsteen/042 - Leonardo.mp3`
|
|
* - The folder name must only consist of two digits, additional chars are
|
|
* not allowed in the folder name
|
|
* - `9/42.mp3`
|
|
* - Leading zeros must be added, e.g. `09/042.mp3` would be valid
|
|
* - `99/359.mp3`
|
|
* - Folder number out of range (1-255 is valid)
|
|
*
|
|
* Numbered File Inside MP3 Folder Naming Scheme
|
|
* ---------------------------------------------
|
|
*
|
|
* The MP3 files have to be named with four decimal digits and must be placed in
|
|
* the folder `"MP3"`. Subsequent characters after the four digits are ignored.
|
|
* Valid names are e.g. `MP3/0001.mp3` or `MP3/0042 - My favorite song.mp3`. The
|
|
* file numbers 1-9999 are valid. Playback of these files can be started using
|
|
* the function @ref dfplayer_play_from_mp3 .
|
|
*
|
|
* Advertisements
|
|
* --------------
|
|
*
|
|
* MP3 files placed in the folder `"ADVERT"` named with four decimal digits
|
|
* (e.g. `"0001.mp3"` or `"1337.mp3"`) can be played as advertisements: The
|
|
* function @ref dfplayer_play_from_advert can be used to start their playback,
|
|
* but only while a non-advertisement is currently playing. After the
|
|
* advertisement the normal playback is resumed. This feature has been
|
|
* implemented in the hope it is used for features like audible user feedback
|
|
* to controls, rather than playing advertisements.
|
|
*
|
|
* Combining Naming Schemes
|
|
* ------------------------
|
|
*
|
|
* All of the above naming schemes can be used on the same storage device.
|
|
* However, you still have to use to the functions intended to be used with
|
|
* the naming scheme of a specific file in order to be able to play it.
|
|
*
|
|
* Track Numbers
|
|
* =============
|
|
*
|
|
* @warning Track numbers are a bogus unit in the DFPlayer
|
|
*
|
|
* Track numbers in the dfplayer revert to the number of the file in the file
|
|
* system. Without preparing the medium played at a very low level, it will be
|
|
* hard to map track numbers to their corresponding songs. If you started
|
|
* playback using @ref dfplayer_play_file or @ref dfplayer_play_from_mp3, you
|
|
* can use @ref dfplayer_get_played_file to get the currently played filed
|
|
* according to the used naming scheme (see section above).
|
|
*
|
|
* Continuous Playback
|
|
* ===================
|
|
*
|
|
* The are two options for achieving continuous playback with the DFPlayer Mini:
|
|
* The first is to use @ref dfplayer_shuffle_all or @ref dfplayer_repeat_folder
|
|
* to schedule shuffled playback of all files or repeat playback of a folder,
|
|
* respectively. But keep in mind that any playback command will switch back to
|
|
* normal playback mode.
|
|
*
|
|
* The second option is to schedule playback of the next file right after the
|
|
* playback of a file has completed. This can be implemented most conveniently
|
|
* by using the callback functions (see @ref dfplayer_set_callbacks). But
|
|
* beware: The callbacks are called in interrupt context and the API of this
|
|
* driver ***MUST ONLY*** be used in thread context.
|
|
*
|
|
* Known Hardware Bugs
|
|
* ===================
|
|
*
|
|
* Device Bugs Not Handled by the Driver
|
|
* -------------------------------------
|
|
*
|
|
* On some versions of the DFPlayer, any UART communication with the device
|
|
* during playback results in audible and unpleasant glitches. The only solution
|
|
* is to not communicate with the device during playback, as the DFPlayer seems
|
|
* to pause playback for some milliseconds after receiving a command. If the
|
|
* busy pin of the DFPlayer is connected to your board and configured, the
|
|
* function @ref dfplayer_get_state will read the busy pin to detect if the
|
|
* DFPlayer is currently playing. Onlyif according to the busy pin the device is
|
|
* not currently playing, the UART interface is used to detect whether the
|
|
* playback is paused or stopped. Thus, @ref dfplayer_get_state can be used
|
|
* without fearing to cause audio glitches, provided the busy pin is connected
|
|
* and configured. You can use this to poll the state of the DPlayer and issue
|
|
* the commands once playback has completed, or use the callbacks (see
|
|
* @ref dfplayer_set_callbacks) to get notified when playback has completed.
|
|
*
|
|
* When playback of a file from the `"ADVERT"` folder is started while the
|
|
* device not playing, or already playing a file from the `"ADVERT"` folder,
|
|
* the command fails to execute and the DFPlayer stops all playback (if
|
|
* currently playing).
|
|
*
|
|
* Device Bugs Handled by the Driver
|
|
* ---------------------------------
|
|
*
|
|
* (These bugs are transparently handled by the driver, so users of the driver
|
|
* can safely skip reading this section.)
|
|
*
|
|
* When playing a file from the MP3 folder or from the ADVERT folder, the
|
|
* DFPlayer acknowledges the command before checking if the file actually
|
|
* exists. If the file does not exist, a second message to indicate the failure
|
|
* is send, but no second message is send on success. If the second message is
|
|
* not received, the driver has to figure out by other means if this is a
|
|
* communication error or indicates that the playback has started. If the
|
|
* busy pin of the DFPlayer is connected and configured, it will be used to
|
|
* verify that the command succeeded. Otherwise, the driver will query the
|
|
* status of the device via UART to confirm that playback started, which can
|
|
* cause audible glitches on some revisions. For those revisions, the busy pin
|
|
* should be really used.
|
|
*
|
|
* When the DFPlayer completes playback of a file, the next command received
|
|
* is not acknowledged, if it is a control command. Query commands are not
|
|
* affected. The driver works around this bug by querying the volume prior to
|
|
* issuing a control command directly after playback completed.
|
|
*
|
|
* Some versions of the DFPlayer are not able to handle commands send at high
|
|
* frequency. A delay of 100ms is inserted after every communication with the
|
|
* device to counter this.
|
|
*
|
|
* Some versions of the DFPlayer have a high chance of ignoring commands. The
|
|
* driver tries up to @ref DFPLAYER_RETRIES (`5` be default) times the command
|
|
* before giving up. For that reason, non-idempotent commands supported by the
|
|
* DFPlayer (e.g. increase and decrease volume) are not exposed by the driver,
|
|
* as retrying could result in them being executed more than once. There are
|
|
* idempotent commands that can achieve the same (e.g. the set volume command
|
|
* instead of increase or decrease volume commands) for every non-idempotent
|
|
* command, so this doesn't restrict the feature set of the driver.
|
|
*
|
|
* @{
|
|
*
|
|
* @file
|
|
* @brief DFPlayer Mini Device Driver
|
|
*
|
|
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
|
|
*/
|
|
|
|
#ifndef DFPLAYER_H
|
|
#define DFPLAYER_H
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
|
|
#include "dfplayer_params.h"
|
|
#include "dfplayer_types.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**
|
|
* @brief The number of milliseconds to wait after receiving playback of file
|
|
* has completed before starting playback of the next file
|
|
*/
|
|
#define DFPLAYER_WAIT_MS (100U)
|
|
|
|
#ifdef MODULE_AUTO_INIT_MULTIMEDIA
|
|
|
|
extern dfplayer_t dfplayer_devs[DFPLAYER_NUMOF];
|
|
|
|
/**
|
|
* @brief Get an auto-initialized DFPlayer Mini device descriptor by number
|
|
* @param num Number of the DFPlayer Mini device descriptor to get
|
|
* @return The DFPlayer Mini device descriptor at index @p num
|
|
* @retval `NULL` @p num is out of range
|
|
*
|
|
* A value of `0` for @p num is used to retrieve the first device descriptor.
|
|
*/
|
|
static inline dfplayer_t * dfplayer_get(unsigned num)
|
|
{
|
|
if (num < DFPLAYER_NUMOF) {
|
|
return &dfplayer_devs[num];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
#endif /* MODULE_AUTO_INIT_MULTIMEDIA */
|
|
|
|
/**
|
|
* @brief Initialize a DFPlayer Mini device descriptor
|
|
*
|
|
* @param dev Device descriptor to initialized
|
|
* @param params Connection parameters to initialize with
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Invalid parameters
|
|
* @retval -EIO Failed to initialize UART interface / GPIO pin
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
*/
|
|
int dfplayer_init(dfplayer_t *dev, const dfplayer_params_t *params);
|
|
|
|
/**
|
|
* @brief Get the set of available playback sources of the given DFPlayer
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer Mini check
|
|
*
|
|
* @return The set of playback sources currently available
|
|
* @retval 0 If @p dev is `NULL` or no source is available
|
|
*/
|
|
dfplayer_source_set_t dfplayer_get_sources(dfplayer_t *dev);
|
|
|
|
/**
|
|
* @brief Set/clear the event callbacks of the DFPlayer Mini
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to update
|
|
* @param cb_done Function to call when playback of a file/track completed
|
|
* @param cb_src Function to call when a source was inserted/ejected
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameter
|
|
*
|
|
* Calling with `NULL` for @p cb_done and/or for @p cb_src clears the
|
|
* corresponding callback functions.
|
|
*
|
|
* @warning The callbacks are called from interrupt context
|
|
*/
|
|
int dfplayer_set_callbacks(dfplayer_t *dev, dfplayer_cb_done_t cb_done,
|
|
dfplayer_cb_src_t cb_src);
|
|
|
|
/**
|
|
* @brief Start playing the next song in the currently used naming scheme
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to control
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameter
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
* @retval -ERANGE The next song is out of range (depending to the
|
|
* currently used naming scheme)
|
|
* @retval -ENOENT No such file
|
|
*
|
|
* If previously @ref dfplayer_play_file was used to start playback of
|
|
* file "42/113.mp3", this call will try to start "42/114.mp3". If previously
|
|
* @ref dfplayer_play_from_mp3 was used to start playback of file
|
|
* "MP3/1337.mp3", this call will try to start "MP3/1338.mp3".
|
|
*/
|
|
static inline int dfplayer_next(dfplayer_t *dev);
|
|
|
|
/**
|
|
* @brief Start playing the previous song in the currently used naming scheme
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to control
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameter
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
* @retval -ERANGE The next song is out of range (depending to the
|
|
* currently used naming scheme)
|
|
* @retval -ENOENT No such file
|
|
*
|
|
* If previously @ref dfplayer_play_file was used to start playback of
|
|
* file "42/113.mp3", this call will try to start "42/112.mp3". If previously
|
|
* @ref dfplayer_play_from_mp3 was used to start playback of file
|
|
* "MP3/1337.mp3", this call will try to start "MP3/1336.mp3".
|
|
*/
|
|
static inline int dfplayer_prev(dfplayer_t *dev);
|
|
|
|
/**
|
|
* @brief Step forward/backward following the currently used naming scheme
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to control
|
|
* @param step Steps to take (negative for previous files)
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameter
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
* @retval -ERANGE The next song is out of range (depending to the
|
|
* currently used naming scheme)
|
|
* @retval -ENOENT No such file
|
|
*
|
|
* Calling with a value of `1` for @p step is equivalent to @ref dfplayer_next,
|
|
* calling with a value of `-1` for @p step is equivalent to @ref dfplayer_prev.
|
|
* A value of `0` will restart the currently played song
|
|
*/
|
|
int dfplayer_step(dfplayer_t *dev, int step);
|
|
|
|
/**
|
|
* @brief Sets the volume to the given value
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to control
|
|
* @param volume Volume to set (max 30)
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameters
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
*
|
|
* If @p volume is greater than the maximum allowed volume of 30, 30 will be
|
|
* send instead.
|
|
*/
|
|
static inline int dfplayer_set_volume(dfplayer_t *dev, uint8_t volume);
|
|
|
|
/**
|
|
* @brief Apply the given equalizer setting
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to control
|
|
* @param equalizer The equalizer setting to apply
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameters
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
*/
|
|
static inline int dfplayer_set_equalizer(dfplayer_t *dev,
|
|
dfplayer_eq_t equalizer);
|
|
|
|
/**
|
|
* @brief Apply the given source
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to control
|
|
* @param src The source to use for playback
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameters
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
*/
|
|
static inline int dfplayer_set_source(dfplayer_t *dev, dfplayer_source_t src);
|
|
|
|
/**
|
|
* @brief Enter standby mode
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to control
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameters
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
*/
|
|
static inline int dfplayer_enter_standby(dfplayer_t *dev);
|
|
|
|
/**
|
|
* @brief Exit standby mode
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to control
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameters
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
*/
|
|
static inline int dfplayer_exit_standby(dfplayer_t *dev);
|
|
|
|
/**
|
|
* @brief Start/resume playing
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to control
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameter
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
*/
|
|
static inline int dfplayer_play(dfplayer_t *dev);
|
|
|
|
/**
|
|
* @brief Pause the playback
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to control
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameter
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
*/
|
|
static inline int dfplayer_pause(dfplayer_t *dev);
|
|
|
|
/**
|
|
* @brief Start playing the specified file in the specified folder
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to control
|
|
* @param folder Number of the folder
|
|
* @param file Number of the file
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameters (see precondition)
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
* @retval -ENOENT Specified file and/or folder does not exist
|
|
*
|
|
* @pre `0 < folder <= 100` and `file > 0`
|
|
*
|
|
* E.g. when called with @p folder set to `9` and @p file set to `42`, the
|
|
* file `"09/042.mp3"` is played. Thus, the folder and file names need to
|
|
* follow a specific naming convention in order to be selectable with this
|
|
* function.
|
|
*/
|
|
int dfplayer_play_file(dfplayer_t *dev, uint8_t folder, uint8_t file);
|
|
|
|
/**
|
|
* @brief Start playing the specified number in the MP3 folder
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to control
|
|
* @param number Number of the file in the folder `"MP3"` to play
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameters (see precondition)
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
* @retval -ENOENT Specified number does not exist
|
|
*
|
|
* @pre `0 < number <= 9999`
|
|
*
|
|
* E.g. when called with @p number set to `42`, the file `"MP3/0042.mp3"` is
|
|
* played. Thus, the folder and file names need to follow a specific naming
|
|
* convention in order to be selectable with this function.
|
|
*/
|
|
int dfplayer_play_from_mp3(dfplayer_t *dev, uint16_t number);
|
|
|
|
/**
|
|
* @brief Start playing the specified number in the ADVERT folder
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to control
|
|
* @param number Number of the number in the folder `"ADVERT"` to play
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameters (see precondition)
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
* @retval -ENOENT Specified number does not exist
|
|
*
|
|
* @pre `0 < number <= 9999`
|
|
* @warning The playback is only started when the DFPlayer is currently playing
|
|
* a non-advert file. The current playback is paused, the advert-file
|
|
* is played, and the previous playback is resumed afterwards
|
|
* @note While this feature was obviously added to allow playing
|
|
* advertisements, this function was provided in the best hope it is
|
|
* not used this way.
|
|
*
|
|
* E.g. when called with @p number set to `42`, the file `"ADVERT/0042.mp3"` is
|
|
* played. Thus, the folder and file names need to follow a specific naming
|
|
* convention in order to be selectable with this function.
|
|
*
|
|
* The most obvious use (apart for advertisements `:-/`) is to use it for
|
|
* audible feedback to control commands. E.g. when the user changes the volume,
|
|
* a short "boing" sound could be played. That would allow the user to perceive
|
|
* the configured volume, even if currently played song is silent while
|
|
* configuring the volume.
|
|
*/
|
|
int dfplayer_play_from_advert(dfplayer_t *dev, uint16_t number);
|
|
|
|
/**
|
|
* @brief Stop playing a file from the ADVERT folder and resume previous playback
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to control
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameters (see precondition)
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
*/
|
|
static inline int dfplayer_stop_advert(dfplayer_t *dev);
|
|
|
|
/**
|
|
* @brief Start playing and repeating the specified folder
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to control
|
|
* @param folder Number of the folder to play and repeat
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameters (see precondition)
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
* @retval -ENOENT Specified file and/or folder does not exist
|
|
*
|
|
* @pre `0 < folder <= 100` and `file > 0`
|
|
*/
|
|
static inline int dfplayer_repeat_folder(dfplayer_t *dev, uint8_t folder);
|
|
|
|
/**
|
|
* @brief Launch shuffle playback of all files
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to control
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameters (see precondition)
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
* @retval -ENOENT Specified file and/or folder does not exist
|
|
*
|
|
* @warning Even files in the `"ADVERT"` folder are played
|
|
*/
|
|
static inline int dfplayer_shuffle_all(dfplayer_t *dev);
|
|
|
|
/**
|
|
* @brief Enable or disable repeat playback
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to control
|
|
* @param repeat Enable repeat playback?
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameters (see precondition)
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
* @retval -ENOENT Specified file and/or folder does not exist
|
|
*/
|
|
static inline int dfplayer_repeat(dfplayer_t *dev, bool repeat);
|
|
|
|
/**
|
|
* @brief Query the state of the DFPlayer Mini
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to query
|
|
* @param state The state will be stored here
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameters
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
*
|
|
* @note This function will work best when the busy pin is connected and
|
|
* and configured, as this can avoid UART communication if the device
|
|
* is currently playing. (Remember that UART communication results
|
|
* in audible glitches during playback...)
|
|
*/
|
|
int dfplayer_get_state(dfplayer_t *dev, dfplayer_state_t *state);
|
|
|
|
/**
|
|
* @brief Query the current volume of the DFPlayer Mini
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to query
|
|
* @param volume The volume will be stored here
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameters
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
*/
|
|
static inline int dfplayer_get_volume(dfplayer_t *dev, uint8_t *volume);
|
|
|
|
/**
|
|
* @brief Query the current equalizer setting of the DFPlayer Mini
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to query
|
|
* @param equalizer The equalizer setting will be stored here
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameters
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
*/
|
|
static inline int dfplayer_get_equalizer(dfplayer_t *dev,
|
|
dfplayer_eq_t *equalizer);
|
|
|
|
/**
|
|
* @brief Query the current playback mode of the DFPlayer Mini
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to query
|
|
* @param mode The playback mode will be stored here
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameters
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
*/
|
|
static inline int dfplayer_get_mode(dfplayer_t *dev,
|
|
dfplayer_mode_t *mode);
|
|
|
|
/**
|
|
* @brief Query the software version running on the DFPlayer Mini
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to query
|
|
* @param version The software version will be stored here
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameters
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
*/
|
|
static inline int dfplayer_get_version(dfplayer_t *dev, uint16_t *version);
|
|
|
|
/**
|
|
* @brief Query the number of files on the USB storage device
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to query
|
|
* @param files The number of files will be stored here
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameters
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
*/
|
|
static inline int dfplayer_files_usb(dfplayer_t *dev, uint16_t *files);
|
|
|
|
/**
|
|
* @brief Query the number of files on the SD card
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to query
|
|
* @param files The number of files will be stored here
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameters
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
*/
|
|
static inline int dfplayer_files_sdcard(dfplayer_t *dev, uint16_t *files);
|
|
|
|
/**
|
|
* @brief Query the number of files on the NOR flash
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to query
|
|
* @param files The number of files will be stored here
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameters
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
*/
|
|
static inline int dfplayer_files_flash(dfplayer_t *dev, uint16_t *files);
|
|
|
|
/**
|
|
* @brief Query the selected file on the USB storage device
|
|
*
|
|
* @warning The file number refers to the internal file system order
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to query
|
|
* @param fileno The selected file will be stored here
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameters
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
*/
|
|
static inline int dfplayer_get_fileno_usb(dfplayer_t *dev, uint16_t *fileno);
|
|
|
|
/**
|
|
* @brief Query the selected file on the SD card
|
|
*
|
|
* @warning The file number refers to the internal file system order
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to query
|
|
* @param fileno The selected file will be stored here
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameters
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
*/
|
|
static inline int dfplayer_get_fileno_sdcard(dfplayer_t *dev, uint16_t *fileno);
|
|
|
|
/**
|
|
* @brief Query the selected file on the NOR flash
|
|
*
|
|
* @warning The file number refers to the internal file system order
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to query
|
|
* @param fileno The selected file will be stored here
|
|
*
|
|
* @retval 0 Success
|
|
* @retval -EINVAL Called with invalid parameters
|
|
* @retval -EIO Communication with the DFPlayer Mini failed
|
|
* @retval -EAGAIN DFPlayer responded with error "Device busy"
|
|
* @retval -ETIMEDOUT Response of the DFPlayer timed out
|
|
*/
|
|
static inline int dfplayer_get_fileno_flash(dfplayer_t *dev, uint16_t *fileno);
|
|
|
|
/**
|
|
* @brief Get the currently played file and the used naming scheme
|
|
*
|
|
* @param dev Device descriptor of the DFPlayer to query
|
|
*
|
|
* @return The currently played file and the used naming scheme
|
|
*/
|
|
static inline dfplayer_file_t dfplayer_get_played_file(dfplayer_t *dev);
|
|
|
|
/**
|
|
* @brief Check if the given source set contains the given source
|
|
*
|
|
* @param set Set of sources to check
|
|
* @param src Source to check for
|
|
*
|
|
* @retval 0 @p src is ***NOT*** part of @p set
|
|
* @retval 1 @p src ***IS*** part of @p set
|
|
*/
|
|
static inline int dfplayer_source_set_contains(dfplayer_source_set_t set,
|
|
dfplayer_source_t src);
|
|
|
|
/**
|
|
* @brief Add the given source to the given source set
|
|
*
|
|
* @param set Set of sources to add source to
|
|
* @param src Source to add
|
|
*
|
|
* This function is idempotent
|
|
*/
|
|
static inline void dfplayer_source_set_add(dfplayer_source_set_t *set,
|
|
dfplayer_source_t src);
|
|
|
|
/**
|
|
* @brief Remove the given source to the given source set
|
|
*
|
|
* @param set Set of sources to remove the source from
|
|
* @param src Source to remove
|
|
*
|
|
* This function is idempotent
|
|
*/
|
|
static inline void dfplayer_source_set_rm(dfplayer_source_set_t *set,
|
|
dfplayer_source_t src);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
/* Include implementation of the static inline functions */
|
|
#include "dfplayer_implementation.h"
|
|
|
|
#endif /* DFPLAYER_H */
|
|
/** @} */
|