many changes :Py
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
#ifndef AUDIODATA_H
|
||||
#define AUDIODATA_H
|
||||
|
||||
#define min(a,b) ( (a<b) ? (a) : (b) )
|
||||
|
||||
|
||||
struct Data {
|
||||
const uint8_t* data;
|
||||
@@ -14,6 +14,10 @@ struct AudioData {
|
||||
const uint8_t* data;
|
||||
uint32_t available;
|
||||
|
||||
static uint32_t min(uint32_t a, uint32_t b) {
|
||||
return (a<b) ? (a) : (b);
|
||||
}
|
||||
|
||||
AudioData() : data(nullptr), available(0) {;}
|
||||
|
||||
AudioData(const uint8_t* data, const uint32_t len) : data(data), available(len) {
|
||||
|
||||
@@ -1,34 +1,38 @@
|
||||
#ifndef VS1003_H
|
||||
#define VS1003_H
|
||||
|
||||
#include "io/fastGPIO.h"
|
||||
#include "../io/SoftSPI.h"
|
||||
#include "../../io/fastGPIO.h"
|
||||
#include "../../io/SoftSPI.h"
|
||||
#include "../../Debug.h"
|
||||
//#include "IPlayable.h"
|
||||
#include "AudioData.h"
|
||||
//#include "AudioData.h"
|
||||
#include "../../data/ChunkBuffer.h"
|
||||
|
||||
|
||||
/**
|
||||
* control a VS1003 audio chip attached to the SPI port
|
||||
*/
|
||||
class VS1003 {
|
||||
template <typename PlayBuf> class VS1003 {
|
||||
|
||||
private:
|
||||
|
||||
SoftSPI spi;
|
||||
#define SPI_INIT() spi.init();
|
||||
#define SPI_WRITE_8(byte) spi.writeByte(byte)
|
||||
#define SPI_WRITE_16(word) spi.writeWord(word)
|
||||
#define SPI_READ_8(byte) spi.readByte(byte)
|
||||
#define SPI_READ_16(word) spi.readWord(word)
|
||||
#define SPI_READ_WRITE_8(byte) spi.readWriteByte(byte)
|
||||
#define SPI_READ_WRITE_16(word) spi.readWriteWord(word)
|
||||
static constexpr const char* NAME = "VS1003";
|
||||
|
||||
//SoftSPI spi;
|
||||
#define SPI_INIT() spi::init();
|
||||
#define SPI_WRITE_8(byte) spi::writeByte(byte)
|
||||
#define SPI_WRITE_16(word) spi::writeWord(word)
|
||||
#define SPI_READ_8(byte) spi::readByte(byte)
|
||||
#define SPI_READ_16(word) spi::readWord(word)
|
||||
#define SPI_READ_WRITE_8(byte) spi::readWriteByte(byte)
|
||||
#define SPI_READ_WRITE_16(word) spi::readWriteWord(word)
|
||||
//#define SPI_DELAY() os_delay_us(10)
|
||||
#define SPI_DELAY() //os_delay_us(10)
|
||||
|
||||
#define GET_DREQ() GPIO16_IN // PIN D0
|
||||
|
||||
|
||||
#define MP3_CTRL_DESELECT() spi.chipDeselect();
|
||||
#define MP3_CTRL_SELECT() spi.chipSelect();
|
||||
#define MP3_CTRL_DESELECT() spi::chipDeselect();
|
||||
#define MP3_CTRL_SELECT() spi::chipSelect();
|
||||
#define MP3_DATA_DESELECT() GPIO5_H
|
||||
#define MP3_DATA_SELECT() GPIO5_L
|
||||
|
||||
@@ -92,9 +96,15 @@ public:
|
||||
|
||||
public:
|
||||
|
||||
VS1003() {
|
||||
init();
|
||||
}
|
||||
|
||||
/** initialize the hardware */
|
||||
void init() {
|
||||
|
||||
debugMod(NAME, "init()");
|
||||
|
||||
SPI_INIT();
|
||||
|
||||
GPIO5_OUTPUT_SET; // Pin D1 - XDCS
|
||||
@@ -103,6 +113,7 @@ public:
|
||||
this->state = PlayState::STOPPED;
|
||||
|
||||
awaitDREQ(); // Wait for the VS1003 to finish boot
|
||||
|
||||
reset();
|
||||
|
||||
}
|
||||
@@ -112,6 +123,7 @@ public:
|
||||
* @param Audio volume to set on both channels.
|
||||
*/
|
||||
void setVolume(const uint8_t vol) const {
|
||||
debugMod1(NAME, "setVolume(%d)", vol);
|
||||
const uint8_t aVol = 255 - vol;
|
||||
const uint16_t values = (aVol << 0) | (aVol << 8); // left and right
|
||||
writeRegister(SCI_VOL, values);
|
||||
@@ -122,10 +134,16 @@ public:
|
||||
return (255 - (values & 0xFF));
|
||||
}
|
||||
|
||||
void play(AudioData ad) {
|
||||
this->playable = ad;
|
||||
this->state = PlayState::PLAYING;
|
||||
}
|
||||
// void play(AudioData ad) {
|
||||
// this->playable = ad;
|
||||
// this->state = PlayState::PLAYING;
|
||||
// }
|
||||
|
||||
// void appendUnmanaged(const uint8_t* data, const uint16_t size) {
|
||||
// ChunkBuffer::Chunk* c = playBuf.wrap(data, size);
|
||||
// playBuf.append(c);
|
||||
// this->state = PlayState::PLAYING;
|
||||
// }
|
||||
|
||||
void ICACHE_FLASH_ATTR record(RecordSource source) {
|
||||
|
||||
@@ -164,18 +182,22 @@ public:
|
||||
return this->state;
|
||||
}
|
||||
|
||||
void play() {
|
||||
//if(this->state == PlayState::STOPPED) { reset(); } // makes things more stable
|
||||
this->state = PlayState::PLAYING;
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR run() {
|
||||
if(this->state == PlayState::PLAYING) {
|
||||
if (!playable.isEOF()) {
|
||||
const Data chunk = playable.read(32);
|
||||
playChunk32(chunk.data, chunk.len);
|
||||
if (playBuf.empty()) {
|
||||
//uint8_t stopSequence[4] = {0};
|
||||
//playChunk32(stopSequence, sizeof(stopSequence)); // end of stream
|
||||
//this->state = PlayState::STOPPED;
|
||||
} else {
|
||||
this->state = PlayState::STOPPED;
|
||||
uint8_t stopSequence[4] = {0};
|
||||
playChunk32(stopSequence, sizeof(stopSequence));
|
||||
//const ChunkBuffer::Data chunk = playBuf.get(32);
|
||||
//playChunk32(chunk.ptr, chunk.size);
|
||||
sendPlayBuffer();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,6 +239,16 @@ public:
|
||||
|
||||
}
|
||||
|
||||
PlayBuf& getPlayBuffer() {
|
||||
return playBuf;
|
||||
}
|
||||
|
||||
void stop() {
|
||||
this->state = PlayState::STOPPED;
|
||||
playBuf.clear();
|
||||
//reset();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
uint32_t getNumAvailableRecordBytes() {
|
||||
@@ -224,15 +256,30 @@ private:
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR playChunk32(const uint8_t* buffer, const uint32_t len) const {
|
||||
debugMod1(NAME, "playChunk32() len:%d", len);
|
||||
MP3_CTRL_DESELECT();
|
||||
MP3_DATA_SELECT();
|
||||
awaitDREQ();
|
||||
|
||||
for(uint32_t i = 0; i < len; ++i) {
|
||||
awaitDREQ();
|
||||
SPI_WRITE_8(buffer[i]);
|
||||
}
|
||||
MP3_DATA_DESELECT();
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR sendPlayBuffer() {
|
||||
MP3_CTRL_DESELECT();
|
||||
MP3_DATA_SELECT();
|
||||
int written = 0;
|
||||
while(canConsume() && !playBuf.empty()) {
|
||||
const uint8_t byte = playBuf.get();
|
||||
if (byte == -1) {break;}
|
||||
SPI_WRITE_8(byte);
|
||||
++written;
|
||||
}
|
||||
if (written) {debugMod1(NAME, "sendPlayBuffer(): %d bytes", written);}
|
||||
MP3_DATA_DESELECT();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write the given register.
|
||||
@@ -273,7 +320,17 @@ private:
|
||||
* @brief Wait for the VS1003 to set DREQ to high (it wants data).
|
||||
*/
|
||||
inline void awaitDREQ() const {
|
||||
debugMod(NAME, "awaitDREQ()");
|
||||
while(!GET_DREQ()) {;}
|
||||
//debugMod(NAME, "awaitDREQ() complete");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief VS1003 is able do consume data
|
||||
* @return
|
||||
*/
|
||||
inline bool canConsume() const {
|
||||
return GET_DREQ();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -281,6 +338,9 @@ private:
|
||||
* @param modeMask Additional mask to or into the mode that is written to the VS1003's register.
|
||||
*/
|
||||
void reset(Mode modeMask = Mode::NONE) const {
|
||||
|
||||
debugMod(NAME, "reset()");
|
||||
|
||||
writeRegister(SCI_MODE, (2052 | (uint16_t)modeMask)); // TODO: remove SM_TESTS
|
||||
os_delay_us(1);
|
||||
awaitDREQ();
|
||||
@@ -297,13 +357,17 @@ private:
|
||||
|
||||
os_delay_us(100);
|
||||
MP3_CTRL_DESELECT();
|
||||
|
||||
debugMod(NAME, "reset() complete");
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
//IPlayable* playable = nullptr;
|
||||
AudioData playable;
|
||||
|
||||
PlayState state = PlayState::STOPPED;
|
||||
|
||||
PlayBuf playBuf;
|
||||
|
||||
};
|
||||
|
||||
#endif // VS1003_H
|
||||
|
||||
Reference in New Issue
Block a user