Adafruit_VS1053_Library/Adafruit_VS1053.h
2025-06-03 08:53:16 -07:00

427 lines
14 KiB
C++

/*!
* @file Adafruit_VS1053.h
*/
#ifndef ADAFRUIT_VS1053_H
#define ADAFRUIT_VS1053_H
#if (ARDUINO >= 100)
#include <Arduino.h>
#else
#include <WProgram.h>
#include <pins_arduino.h>
#endif
#if !defined(ARDUINO_STM32_FEATHER) && !defined(ARDUINO_UNOR4_WIFI) && \
!defined(ARDUINO_UNOR4_MINIMA)
#include "pins_arduino.h"
#include "wiring_private.h"
#endif
#include <Adafruit_SPIDevice.h>
#if defined(PREFER_SDFAT_LIBRARY)
#include <SdFat.h>
extern SdFat SD;
#else
#include <SD.h>
#endif
// define here the size of a register!
#if defined(ARDUINO_STM32_FEATHER)
typedef volatile uint32 RwReg;
typedef uint32_t PortMask;
#elif defined(ARDUINO_ARCH_AVR)
typedef volatile uint8_t RwReg;
typedef uint8_t PortMask;
#elif defined(__arm__)
#if defined(TEENSYDUINO)
typedef volatile uint8_t RwReg;
typedef uint8_t PortMask;
#else
typedef volatile uint32_t RwReg;
typedef uint32_t PortMask;
#endif
#elif defined(ESP8266) || defined(ESP32)
typedef volatile uint32_t RwReg;
typedef uint32_t PortMask;
#elif defined(__ARDUINO_ARC__)
typedef volatile uint32_t RwReg;
typedef uint32_t PortMask;
#else
typedef volatile uint8_t RwReg; //!< 1-byte read-write register
typedef uint8_t PortMask; //!< Type definition for a bitmask that is used to
//!< specify the bit width
#endif
typedef volatile RwReg PortReg; //!< Type definition/alias used to specify the
//!< port register that a pin is in
#define VS1053_FILEPLAYER_TIMER0_INT \
255 //!< Allows useInterrupt to accept pins 0 to 254
#define VS1053_FILEPLAYER_PIN_INT \
5 //!< Allows useInterrupt to accept pins 0 to 4
#define VS1053_SCI_READ 0x03 //!< Serial read address
#define VS1053_SCI_WRITE 0x02 //!< Serial write address
#define VS1053_REG_MODE 0x00 //!< Mode control
#define VS1053_REG_STATUS 0x01 //!< Status of VS1053b
#define VS1053_REG_BASS 0x02 //!< Built-in bass/treble control
#define VS1053_REG_CLOCKF 0x03 //!< Clock frequency + multiplier
#define VS1053_REG_DECODETIME 0x04 //!< Decode time in seconds
#define VS1053_REG_AUDATA 0x05 //!< Misc. audio data
#define VS1053_REG_WRAM 0x06 //!< RAM write/read
#define VS1053_REG_WRAMADDR 0x07 //!< Base address for RAM write/read
#define VS1053_REG_HDAT0 0x08 //!< Stream header data 0
#define VS1053_REG_HDAT1 0x09 //!< Stream header data 1
#define VS1053_REG_VOLUME 0x0B //!< Volume control
#define VS1053_GPIO_DDR 0xC017 //!< Direction
#define VS1053_GPIO_IDATA 0xC018 //!< Values read from pins
#define VS1053_GPIO_ODATA 0xC019 //!< Values set to the pins
#define VS1053_INT_ENABLE 0xC01A //!< Interrupt enable
#define VS1053_MODE_SM_DIFF \
0x0001 //!< Differential, 0: normal in-phase audio, 1: left channel inverted
#define VS1053_MODE_SM_LAYER12 0x0002 //!< Allow MPEG layers I & II
#define VS1053_MODE_SM_RESET 0x0004 //!< Soft reset
#define VS1053_MODE_SM_CANCEL 0x0008 //!< Cancel decoding current file
#define VS1053_MODE_SM_EARSPKLO 0x0010 //!< EarSpeaker low setting
#define VS1053_MODE_SM_TESTS 0x0020 //!< Allow SDI tests
#define VS1053_MODE_SM_STREAM 0x0040 //!< Stream mode
#define VS1053_MODE_SM_SDINEW 0x0800 //!< VS1002 native SPI modes
#define VS1053_MODE_SM_ADPCM 0x1000 //!< PCM/ADPCM recording active
#define VS1053_MODE_SM_LINE1 0x4000 //!< MIC/LINE1 selector, 0: MICP, 1: LINE1
#define VS1053_MODE_SM_CLKRANGE \
0x8000 //!< Input clock range, 0: 12..13 MHz, 1: 24..26 MHz
#define VS1053_SCI_AIADDR \
0x0A //!< Indicates the start address of the application code written earlier
//!< with SCI_WRAMADDR and SCI_WRAM registers.
#define VS1053_SCI_AICTRL0 \
0x0C //!< SCI_AICTRL register 0. Used to access the user's application program
#define VS1053_SCI_AICTRL1 \
0x0D //!< SCI_AICTRL register 1. Used to access the user's application program
#define VS1053_SCI_AICTRL2 \
0x0E //!< SCI_AICTRL register 2. Used to access the user's application program
#define VS1053_SCI_AICTRL3 \
0x0F //!< SCI_AICTRL register 3. Used to access the user's application program
#define VS1053_SCI_WRAM 0x06 //!< RAM write/read
#define VS1053_SCI_WRAMADDR 0x07 //!< Base address for RAM write/read
#define VS1053_PARA_PLAYSPEED 0x1E04 //!< 0,1 = normal speed, 2 = 2x, 3 = 3x etc
#define VS1053_DATABUFFERLEN 32 //!< Length of the data buffer
/*!
* Driver for the Adafruit VS1053
*/
class Adafruit_VS1053 {
public:
/*!
* @brief Software SPI constructor - must specify all pins
* @param mosi MOSI (Microcontroller Out Serial In) pin
* @param miso MISO (Microcontroller In Serial Out) pin
* @param clk Clock pin
* @param rst Reset pin
* @param cs SCI Chip Select pin
* @param dcs SDI Chip Select pin
* @param dreq Data Request pin
*/
Adafruit_VS1053(int8_t mosi, int8_t miso, int8_t clk, int8_t rst, int8_t cs,
int8_t dcs, int8_t dreq);
/*!
* @brief Hardware SPI constructor - assumes hardware SPI pins
* @param rst Reset pin
* @param cs SCI Chip Select pin
* @param dcs SDI Chip Select pin
* @param dreq Data Request pin
*/
Adafruit_VS1053(int8_t rst, int8_t cs, int8_t dcs, int8_t dreq);
/*!
* @brief Initialize communication and (hard) reset the chip.
* @return Returns true if a VS1053 is found
*/
uint8_t begin(void);
/*!
* @brief Performs a hard reset of the chip
*/
void reset(void);
/*!
* @brief Attempts a soft reset of the chip
*/
void softReset(void);
/*!
* @brief Reads from the specified register on the chip
* @param addr Register address to read from
* @return Retuns the 16-bit data corresponding to the received address
*/
uint16_t sciRead(uint8_t addr);
/*!
* @brief Writes to the specified register on the chip
* @param addr Register address to write to
* @param data Data to write
*/
void sciWrite(uint8_t addr, uint16_t data);
/*!
* @brief Generate a sine-wave test signal
* @param n Defines the sine test to use
* @param ms Delay (in ms)
*/
void sineTest(uint8_t n, uint16_t ms);
/*!
* @brief Reads the DECODETIME register from the chip
* @return Returns the decode time as an unsigned 16-bit integer
*/
uint16_t decodeTime(void);
/*!
* @brief Set the output volume for the chip
* @param left Desired left channel volume
* @param right Desired right channel volume
*/
void setVolume(uint8_t left, uint8_t right);
/*!
* @brief Prints the contents of the MODE, STATUS, CLOCKF and VOLUME registers
*/
void dumpRegs(void);
/*!
* @brief Decode and play the contents of the supplied buffer
* @param buffer Buffer to decode and play
* @param buffsiz Size to decode and play
*/
void playData(uint8_t *buffer, uint8_t buffsiz);
/*!
* @brief Test if ready for more data
* @return Returns true if it is ready for data
*/
boolean readyForData(void);
/*!
* @brief Apply a code patch
* @param patch Patch to apply
* @param patchsize Patch size
*/
void applyPatch(const uint16_t *patch, uint16_t patchsize);
/*!
* @brief Load the specified plug-in
* @param fn Plug-in to load
* @return Either returns 0xFFFF if there is an error, or the address of the
* plugin that was loaded
*/
uint16_t loadPlugin(char *fn);
/*!
* @brief Write to a GPIO pin
* @param i GPIO pin to write to
* @param val Value to write
*/
void GPIO_digitalWrite(uint8_t i, uint8_t val);
/*!
* @brief Write to all 8 GPIO pins at once
* @param i Value to write
*/
void GPIO_digitalWrite(uint8_t i);
/*!
* @brief Read all 8 GPIO pins at once
* @return Returns a 2 byte value with the reads from the 8 pins
*/
uint16_t GPIO_digitalRead(void);
/*!
* @brief Read a single GPIO pin
* @param i pin to read
* @return Returns the state of the specified GPIO pin
*/
boolean GPIO_digitalRead(uint8_t i);
/*!
* @brief Set the Pin Mode (INPUT/OUTPUT) for a GPIO pin.
* @param i Pin to set the mode for
* @param dir Mode to set
*/
void GPIO_pinMode(uint8_t i, uint8_t dir);
/*!
* @brief Initialize chip for OGG recording
* @param plugin Binary file of the plugin to use
* @return Returns true if the device is ready to record
*/
boolean prepareRecordOgg(char *plugin);
/*!
* @brief Start recording
* @param mic mic=true for microphone input
*/
void startRecordOgg(boolean mic);
/*!
* @brief Stop the recording
*/
void stopRecordOgg(void);
/*!
* @brief Returns the number of words recorded
* @return 2-byte unsigned int with the number of words
*/
uint16_t recordedWordsWaiting(void);
/*!
* @brief Reads the next word from the buffer of recorded words
* @return Returns the 16-bit data corresponding to the received address
*/
uint16_t recordedReadWord(void);
uint8_t mp3buffer[VS1053_DATABUFFERLEN]; //!< mp3 buffer that gets sent to the
//!< device
#ifdef ARDUINO_ARCH_SAMD
protected:
uint32_t _dreq; //!< Data request pin
boolean usingInterrupts = false; //!< True if using interrupts
private:
Adafruit_SPIDevice *spi_dev_ctrl = NULL; ///< Pointer to SPI dev for control
Adafruit_SPIDevice *spi_dev_data = NULL; ///< Pointer to SPI dev for data
int32_t _mosi, _miso, _clk, _reset, _cs, _dcs;
boolean useHardwareSPI;
#else
protected:
uint8_t _dreq; //!< Data request pin
boolean usingInterrupts = false; //!< True if using interrupts
private:
Adafruit_SPIDevice *spi_dev_ctrl = NULL; ///< Pointer to SPI dev for control
Adafruit_SPIDevice *spi_dev_data = NULL; ///< Pointer to SPI dev for data
int8_t _mosi, _miso, _clk, _reset, _cs, _dcs;
boolean useHardwareSPI;
#endif
};
/*!
* @brief File player for the Adafruit VS1053
*/
class Adafruit_VS1053_FilePlayer : public Adafruit_VS1053 {
public:
/*!
* @brief Software SPI constructor. Uses Software SPI, so you must specify all
* SPI pins
* @param mosi MOSI (Microcontroller Out Serial In) pin
* @param miso MISO (Microcontroller In Serial Out) pin
* @param clk Clock pin
* @param rst Reset pin
* @param cs SCI Chip Select pin
* @param dcs SDI Chip Select pin
* @param dreq Data Request pin
* @param cardCS CS pin for the SD card on the SPI bus
*/
Adafruit_VS1053_FilePlayer(int8_t mosi, int8_t miso, int8_t clk, int8_t rst,
int8_t cs, int8_t dcs, int8_t dreq, int8_t cardCS);
/*!
* @brief Hardware SPI constructor. Uses Hardware SPI and assumes the default
* SPI pins
* @param rst Reset pin
* @param cs SCI Chip Select pin
* @param dcs SDI Chip Select pin
* @param dreq Data Request pin
* @param cardCS CS pin for the SD card on the SPI bus
*/
Adafruit_VS1053_FilePlayer(int8_t rst, int8_t cs, int8_t dcs, int8_t dreq,
int8_t cardCS);
/*!
* @brief Hardware SPI constructor. Uses Hardware SPI and assumes the default
* SPI pins
* @param cs SCI Chip Select pin
* @param dcs SDI Chip Select pin
* @param dreq Data Request pin
* @param cardCS CS pin for the SD card on the SPI bus
*/
Adafruit_VS1053_FilePlayer(int8_t cs, int8_t dcs, int8_t dreq, int8_t cardCS);
/*!
* @brief Initialize communication and reset the chip.
* @return Returns true if a VS1053 is found
*/
boolean begin(void);
/*!
* @brief Specifies the argument to use for interrupt-driven playback
* @param type interrupt to use. Valid arguments are
* VS1053_FILEPLAYER_TIMER0_INT and VS1053_FILEPLAYER_PIN_INT
* @return Returs true/false for success/failure
*/
boolean useInterrupt(uint8_t type);
File currentTrack; //!< File that is currently playing
volatile boolean playingMusic; //!< Whether or not music is playing
/*!
* @brief Feeds the buffer. Reads mp3 file data from the SD card and file and
* puts it into the buffer that the decoder reads from to play a file
*/
void feedBuffer(void);
/*!
* @brief Checks if the inputted filename is an mp3
* @param fileName File to check
* @return Returns true or false
*/
static boolean isMP3File(const char *fileName);
/*!
* @brief Checks for an ID3 tag at the beginning of the file.
* @param mp3 File to read
* @return returns the seek position within the file where the mp3 data starts
*/
unsigned long mp3_ID3Jumper(File mp3);
/*!
* @brief Begin playing the specified file from the SD card using
* interrupt-drive playback.
* @param *trackname File to play
* @return Returns true when file starts playing
*/
boolean startPlayingFile(const char *trackname);
/*!
* @brief Play the complete file. This function will not return until the
* playback is complete
* @param *trackname File to play
* @return Returns true when file starts playing
*/
boolean playFullFile(const char *trackname);
void stopPlaying(void); //!< Stop playback
/*!
* @brief If playback is paused
* @return Returns true if playback is paused
*/
boolean paused(void);
/*!
* @brief If playback is stopped
* @return Returns true if playback is stopped
*/
boolean stopped(void);
/*!
* @brief Pause playback
* @param pause whether or not to pause playback
*/
void pausePlaying(boolean pause);
/*!
* @brief Set state for playback looping
* @param loopState Sets playback loop state (Note: Only use with
* startPlayingFile, if used with playFullFile no subsequent code in the
* sketch executes)
*/
void playbackLoop(boolean loopState);
/*!
* @brief Retrieve playback loop state
* @return Returns true when looped playback is enabled
*/
boolean playbackLooped();
/*!
* @brief Determine current playback speed
* @return Returns playback speed, i.e. 1 for 1x, 2 for 2x, 3 for 3x
*/
uint16_t getPlaySpeed();
/*!
* @brief Set playback speed
* @param speed Set playback speed, i.e. 1 for 1x, 2 for 2x, 3 for 3x
*/
void setPlaySpeed(uint16_t speed);
private:
void feedBuffer_noLock(void);
uint8_t _cardCS;
};
#endif // ADAFRUIT_VS1053_H