-
Notifications
You must be signed in to change notification settings - Fork 431
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Initial SPIRAM buffering support Signed-off-by: sebastien <armseb@MacBook-de-sebastien.local> * SPI RAM Buffering fill & read. Signed-off-by: sebastien <armseb@MacBook-de-sebastien.local> * First "working" version... Signed-off-by: sebastien <armseb@MacBook-de-sebastien.local> * Improved version of SPIRAM buffering Signed-off-by: Sebastien Decourriere <sebtx452@gmail.com> * Fixed spiram.h path Signed-off-by: Sebastien Decourriere <sebtx452@gmail.com> * Buffer fill optimization Signed-off-by: Sebastien Decourriere <sebtx452@gmail.com> * Modified read block min to avoid too little buffering attempts Signed-off-by: Sebastien Decourriere <sebtx452@gmail.com> * Temps buffer size decrease from 2048 to 1600 Bytes Signed-off-by: Sebastien Decourriere <sebtx452@gmail.com> * Decrease the temp buffer to 256Bytes Signed-off-by: Sebastien Decourriere <sebtx452@gmail.com> * Local buffer variable Signed-off-by: Sebastien Decourriere <sebtx452@gmail.com> * Added loop function to SPIRAMBuffer that refill it automatically Signed-off-by: sebastien <armseb@MacBook-de-sebastien.local> * Compile issue Signed-off-by: sebastien <armseb@MacBook-de-sebastien.local> * Add possibility to define Chip Select pin from Sketch Signed-off-by: Sebastien Decourriere <sebtx452@gmail.com> * Externalize libspiram Signed-off-by: sebastien <armseb@MacBook-de-sebastien.local> * Copyright fix Signed-off-by: sebastien <armseb@MacBook-de-sebastien.local> * Deleted embedded libspiram Signed-off-by: sebastien <armseb@MacBook-de-sebastien.local> * Added comments, example and keyword Signed-off-by: sebastien <armseb@MacBook-de-sebastien.local> * README modification Signed-off-by: sebastien <armseb@MacBook-de-sebastien.local> * Correction Signed-off-by: sebastien <armseb@MacBook-de-sebastien.local> * Schema example Signed-off-by: sebastien <armseb@MacBook-de-sebastien.local> * README correction Signed-off-by: sebastien <armseb@MacBook-de-sebastien.local>
- Loading branch information
1 parent
4710347
commit 97c05c9
Showing
6 changed files
with
283 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
62 changes: 62 additions & 0 deletions
62
examples/StreamMP3FromHTTP_SPIRAM/StreamMP3FromHTTP_SPIRAM.ino
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,62 @@ | |||
#include <Arduino.h> | |||
#include <ESP8266WiFi.h> | |||
#include "AudioFileSourceHTTPStream.h" | |||
#include "AudioFileSourceSPIRAMBuffer.h" | |||
#include "AudioGeneratorMP3.h" | |||
#include "AudioOutputI2SNoDAC.h" | |||
|
|||
// To run, set your ESP8266 build to 160MHz, update the SSID info, and upload. | |||
|
|||
// Enter your WiFi setup here: | |||
const char *SSID = "....."; | |||
const char *PASSWORD = "....."; | |||
|
|||
// Randomly picked URL | |||
const char *URL="http://streaming.shoutcast.com/80sPlanet?lang=en-US"; | |||
|
|||
AudioGeneratorMP3 *mp3; | |||
AudioFileSourceHTTPStream *file; | |||
AudioFileSourceSPIRAMBuffer *buff; | |||
AudioOutputI2SNoDAC *out; | |||
|
|||
void setup() | |||
{ | |||
Serial.begin(115200); | |||
delay(1000); | |||
Serial.println("Connecting to WiFi"); | |||
|
|||
WiFi.disconnect(); | |||
WiFi.softAPdisconnect(true); | |||
WiFi.mode(WIFI_STA); | |||
|
|||
WiFi.hostname("melody"); | |||
|
|||
byte zero[] = {0,0,0,0}; | |||
WiFi.config(zero, zero, zero, zero); | |||
|
|||
WiFi.begin(SSID, PASSWORD); | |||
|
|||
// Try forever | |||
while (WiFi.status() != WL_CONNECTED) { | |||
Serial.println("...Connecting to WiFi"); | |||
delay(1000); | |||
} | |||
|
|||
file = new AudioFileSourceHTTPStream(URL); | |||
// Initialize 23LC1024 SPI RAM buffer with chip select ion GPIO4 and ram size of 128KByte | |||
buff = new AudioFileSourceSPIRAMBuffer(file, 4, 131072); | |||
out = new AudioOutputI2SNoDAC(); | |||
mp3 = new AudioGeneratorMP3(); | |||
mp3->begin(buff, out); | |||
} | |||
|
|||
void loop() | |||
{ | |||
if (mp3->isRunning()) { | |||
if (!mp3->loop()) mp3->stop(); | |||
} else { | |||
Serial.printf("MP3 done\n"); | |||
delay(1000); | |||
} | |||
} | |||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,153 @@ | |||
/* | |||
AudioFileSourceSPIRAMBuffer | |||
Buffered file source in external SPI RAM | |||
Copyright (C) 2017 Sebastien Decourriere | |||
Based on AudioFileSourceBuffer class from Earle F. Philhower, III | |||
This program is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
|
|||
#include <Arduino.h> | |||
#include "AudioFileSourceSPIRAMBuffer.h" | |||
|
|||
#pragma GCC optimize ("O3") | |||
|
|||
AudioFileSourceSPIRAMBuffer::AudioFileSourceSPIRAMBuffer(AudioFileSource *source, uint8_t csPin, uint32_t buffSizeBytes) | |||
{ | |||
Spiram = new ESP8266Spiram(csPin, 40e6); | |||
Spiram->begin(); | |||
Spiram->setSeqMode(); | |||
ramSize = buffSizeBytes; | |||
writePtr = 0; | |||
readPtr = 0; | |||
src = source; | |||
length = 0; | |||
filled = false; | |||
bytesAvailable = 0; | |||
Serial.printf("SPI RAM buffer size: %u Bytes\n", ramSize); | |||
} | |||
|
|||
AudioFileSourceSPIRAMBuffer::~AudioFileSourceSPIRAMBuffer() | |||
{ | |||
} | |||
|
|||
bool AudioFileSourceSPIRAMBuffer::seek(int32_t pos, int dir) | |||
{ | |||
// Invalidate | |||
readPtr = 0; | |||
writePtr = 0; | |||
length = 0; | |||
return src->seek(pos, dir); | |||
} | |||
|
|||
bool AudioFileSourceSPIRAMBuffer::close() | |||
{ | |||
return src->close(); | |||
} | |||
|
|||
bool AudioFileSourceSPIRAMBuffer::isOpen() | |||
{ | |||
return src->isOpen(); | |||
} | |||
|
|||
uint32_t AudioFileSourceSPIRAMBuffer::getSize() | |||
{ | |||
return src->getSize(); | |||
} | |||
|
|||
uint32_t AudioFileSourceSPIRAMBuffer::getPos() | |||
{ | |||
return src->getPos(); | |||
} | |||
|
|||
uint32_t AudioFileSourceSPIRAMBuffer::read(void *data, uint32_t len) | |||
{ | |||
uint32_t bytes = 0; | |||
// Check if the buffer isn't empty, otherwise we try to fill completely | |||
if (!filled) { | |||
uint8_t buffer[256]; | |||
writePtr = readPtr = 0; | |||
uint16_t toRead = sizeof(buffer); | |||
// Fill up completely before returning any data at all | |||
Serial.println("Buffering..."); | |||
while (bytesAvailable!=ramSize) { | |||
length = src->read(buffer, toRead); | |||
if(length>0) { | |||
Spiram->write(writePtr, buffer, length); | |||
bytesAvailable+=length; | |||
writePtr = bytesAvailable % ramSize; | |||
if ((ramSize-bytesAvailable)<toRead) { | |||
toRead=ramSize-bytesAvailable; | |||
} | |||
} | |||
} | |||
writePtr = bytesAvailable % ramSize; | |||
filled = true; | |||
Serial.println("Filling Done !"); | |||
} | |||
|
|||
// Serial.printf("Buffer: %u%\n", bytesAvailable*100/ramSize); | |||
|
|||
uint8_t *ptr = reinterpret_cast<uint8_t*>(data); | |||
uint32_t toReadFromBuffer = (len < bytesAvailable) ? len : bytesAvailable; | |||
if (toReadFromBuffer>0) { | |||
// Pull from buffer until we've got none left or we've satisfied the request | |||
Spiram->read(readPtr, ptr, toReadFromBuffer); | |||
readPtr = (readPtr+toReadFromBuffer) % ramSize; | |||
bytes = toReadFromBuffer; | |||
bytesAvailable-=toReadFromBuffer; | |||
len-=toReadFromBuffer; | |||
ptr += toReadFromBuffer; | |||
} | |||
|
|||
// If len>O there is no data left in buffer and we try to read more directly from source. | |||
// Then, we trigger a complete buffer refill | |||
if (len) { | |||
bytes += src->read(ptr, len); | |||
bytesAvailable = 0; | |||
filled = false; | |||
} | |||
return bytes; | |||
} | |||
|
|||
void AudioFileSourceSPIRAMBuffer::fill() | |||
{ | |||
// Make sure the buffer is pre-filled before make partial fill. | |||
if (!filled) return; | |||
|
|||
// Now trying to refill SPI RAM Buffer | |||
uint8_t buffer[128]; | |||
// Make sure there is at least buffer size free in RAM | |||
if ((ramSize - bytesAvailable)<sizeof(buffer)) { | |||
return; | |||
} | |||
uint16_t cnt = src->readNonBlock(buffer, sizeof(buffer)); | |||
if (cnt) { | |||
Spiram->write(writePtr, buffer, cnt); | |||
bytesAvailable+=cnt; | |||
writePtr = (writePtr + cnt) % ramSize; | |||
#ifdef SPIBUF_DEBUG | |||
Serial.printf("SockRead: %u | RamAvail: %u\n", cnt, bytesAvailable); | |||
#endif | |||
} | |||
return; | |||
} | |||
|
|||
bool AudioFileSourceSPIRAMBuffer::loop() | |||
{ | |||
if (!src->loop()) return false; | |||
fill(); | |||
return true; | |||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,61 @@ | |||
/* | |||
AudioFileSourceSPIRAMBuffer | |||
Buffered file source in external SPI RAM | |||
Copyright (C) 2017 Sebastien Decourriere | |||
Based on AudioFileSourceBuffer class from Earle F. Philhower, III | |||
This program is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
|
|||
#ifndef _AUDIOFILESOURCESPIRAMBUFFER_H | |||
#define _AUDIOFILESOURCESPIRAMBUFFER_H | |||
|
|||
#include "AudioFileSource.h" | |||
#include <SPI.h> | |||
#include <ESP8266Spiram.h> // https://github.com/Gianbacchio/ESP8266_Spiram | |||
|
|||
// #define SPIBUF_DEBUG | |||
|
|||
class AudioFileSourceSPIRAMBuffer : public AudioFileSource | |||
{ | |||
public: | |||
AudioFileSourceSPIRAMBuffer(AudioFileSource *in, uint8_t csPin, uint32_t bufferBytes); | |||
virtual ~AudioFileSourceSPIRAMBuffer() override; | |||
|
|||
virtual uint32_t read(void *data, uint32_t len) override; | |||
virtual bool seek(int32_t pos, int dir) override; | |||
virtual bool close() override; | |||
virtual bool isOpen() override; | |||
virtual uint32_t getSize() override; | |||
virtual uint32_t getPos() override; | |||
virtual bool loop() override; | |||
|
|||
private: | |||
virtual void fill(); | |||
|
|||
private: | |||
AudioFileSource *src; | |||
ESP8266Spiram *Spiram; | |||
uint32_t ramSize; | |||
uint32_t writePtr; | |||
uint32_t readPtr; | |||
uint16_t length; | |||
uint32_t bytesAvailable; | |||
bool filled; | |||
}; | |||
|
|||
|
|||
#endif | |||
|