Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ Then initialize the player and use as in following example:

```
player.begin();
player.loadDefaultVs1053Patches();
player.setVolume(VOLUME);
player.switchToMp3Mode();
player.playChunk(sampleMp3, sizeof(sampleMp3));
Expand Down
1 change: 1 addition & 0 deletions examples/Mp3PlayerDemo/Mp3PlayerDemo.ino
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ void setup() {
Serial.println("Hello VS1053!\n");
// initialize a player
player.begin();
player.loadDefaultVs1053Patches();
player.switchToMp3Mode(); // optional, some boards require this
player.setVolume(VOLUME);
}
Expand Down
3 changes: 2 additions & 1 deletion examples/WebRadioDemo/WebRadioDemo.ino
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

Copyright (C) 2018 Vince Gellár (github.com/vincegellar)
Licensed under GNU GPL v3

Wiring:
--------------------------------
| VS1053 | ESP8266 | ESP32 |
Expand Down Expand Up @@ -101,6 +101,7 @@ void setup() {
SPI.begin();

player.begin();
player.loadDefaultVs1053Patches();
player.switchToMp3Mode();
player.setVolume(VOLUME);

Expand Down
73 changes: 52 additions & 21 deletions src/VS1053.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ uint16_t VS1053::read_register(uint8_t _reg) const {
return result;
}

void VS1053::write_register(uint8_t _reg, uint16_t _value) const {
void VS1053::writeRegister(uint8_t _reg, uint16_t _value) const {
control_mode_on();
SPI.write(2); // Write operation
SPI.write(_reg); // Register to write (0..0xF)
Expand Down Expand Up @@ -97,12 +97,12 @@ void VS1053::sdi_send_fillers(size_t len) {
}

void VS1053::wram_write(uint16_t address, uint16_t data) {
write_register(SCI_WRAMADDR, address);
write_register(SCI_WRAM, data);
writeRegister(SCI_WRAMADDR, address);
writeRegister(SCI_WRAM, data);
}

uint16_t VS1053::wram_read(uint16_t address) {
write_register(SCI_WRAMADDR, address); // Start reading from WRAM
writeRegister(SCI_WRAMADDR, address); // Start reading from WRAM
return read_register(SCI_WRAM); // Read back result
}

Expand Down Expand Up @@ -132,7 +132,7 @@ bool VS1053::testComm(const char *header) {
LOG("%s", header); // Show a header

for (i = 0; (i < 0xFFFF) && (cnt < 20); i += delta) {
write_register(SCI_VOL, i); // Write data to SCI_VOL
writeRegister(SCI_VOL, i); // Write data to SCI_VOL
r1 = read_register(SCI_VOL); // Read back for the first time
r2 = read_register(SCI_VOL); // Read back a second time
if (r1 != r2 || i != r1 || i != r2) // Check for 2 equal reads
Expand Down Expand Up @@ -170,12 +170,12 @@ void VS1053::begin() {
if (testComm("Slow SPI,Testing VS1053 read/write registers...\n")) {
//softReset();
// Switch on the analog parts
write_register(SCI_AUDATA, 44101); // 44.1kHz stereo
writeRegister(SCI_AUDATA, 44101); // 44.1kHz stereo
// The next clocksetting allows SPI clocking at 5 MHz, 4 MHz is safe then.
write_register(SCI_CLOCKF, 6 << 12); // Normal clock settings multiplyer 3.0 = 12.2 MHz
writeRegister(SCI_CLOCKF, 6 << 12); // Normal clock settings multiplyer 3.0 = 12.2 MHz
// SPI Clock to 4 MHz. Now you can set high speed SPI clock.
VS1053_SPI = SPISettings(4000000, MSBFIRST, SPI_MODE0);
write_register(SCI_MODE, _BV(SM_SDINEW) | _BV(SM_LINE1));
writeRegister(SCI_MODE, _BV(SM_SDINEW) | _BV(SM_LINE1));
testComm("Fast SPI, Testing VS1053 read/write registers again...\n");
delay(10);
await_data_request();
Expand Down Expand Up @@ -204,7 +204,7 @@ void VS1053::setVolume(uint8_t vol) {
valueL = map(valueL, 0, 100, 0xFE, 0x00); // 0..100% to left channel
valueR = map(valueR, 0, 100, 0xFE, 0x00); // 0..100% to right channel

write_register(SCI_VOL, (valueL << 8) | valueR); // Volume left and right
writeRegister(SCI_VOL, (valueL << 8) | valueR); // Volume left and right
}

void VS1053::setBalance(int8_t balance) {
Expand All @@ -225,7 +225,7 @@ void VS1053::setTone(uint8_t *rtone) { // Set bass/treble (4 nibbles)
for (i = 0; i < 4; i++) {
value = (value << 4) | rtone[i]; // Shift next nibble in
}
write_register(SCI_BASS, value); // Volume left and right
writeRegister(SCI_BASS, value); // Volume left and right
}

uint8_t VS1053::getVolume() { // Get the currenet volume setting.
Expand All @@ -250,7 +250,7 @@ void VS1053::stopSong() {

sdi_send_fillers(2052);
delay(10);
write_register(SCI_MODE, _BV(SM_SDINEW) | _BV(SM_CANCEL));
writeRegister(SCI_MODE, _BV(SM_SDINEW) | _BV(SM_CANCEL));
for (i = 0; i < 200; i++) {
sdi_send_fillers(32);
modereg = read_register(SCI_MODE); // Read status
Expand All @@ -266,7 +266,7 @@ void VS1053::stopSong() {

void VS1053::softReset() {
LOG("Performing soft-reset\n");
write_register(SCI_MODE, _BV(SM_SDINEW) | _BV(SM_RESET));
writeRegister(SCI_MODE, _BV(SM_SDINEW) | _BV(SM_RESET));
delay(10);
await_data_request();
}
Expand Down Expand Up @@ -347,20 +347,51 @@ uint16_t VS1053::getDecodedTime() {
* byteRate calculation.
*/
void VS1053::clearDecodedTime() {
write_register(SCI_DECODE_TIME, 0x00);
write_register(SCI_DECODE_TIME, 0x00);
writeRegister(SCI_DECODE_TIME, 0x00);
writeRegister(SCI_DECODE_TIME, 0x00);
}

/**
* Fine tune the data rate
*/
void VS1053::adjustRate(long ppm2) {
write_register(SCI_WRAMADDR, 0x1e07);
write_register(SCI_WRAM, ppm2);
write_register(SCI_WRAM, ppm2 >> 16);
writeRegister(SCI_WRAMADDR, 0x1e07);
writeRegister(SCI_WRAM, ppm2);
writeRegister(SCI_WRAM, ppm2 >> 16);
// oldClock4KHz = 0 forces adjustment calculation when rate checked.
write_register(SCI_WRAMADDR, 0x5b1c);
write_register(SCI_WRAM, 0);
writeRegister(SCI_WRAMADDR, 0x5b1c);
writeRegister(SCI_WRAM, 0);
// Write to AUDATA or CLOCKF checks rate and recalculates adjustment.
write_register(SCI_AUDATA, read_register(SCI_AUDATA));
}
writeRegister(SCI_AUDATA, read_register(SCI_AUDATA));
}

/**
* Load a patch or plugin
*/
void VS1053::loadUserCode(const unsigned short* plugin) {
int i = 0;
while (i<sizeof(plugin)/sizeof(plugin[0])) {
unsigned short addr, n, val;
addr = plugin[i++];
n = plugin[i++];
if (n & 0x8000U) { /* RLE run, replicate n samples */
n &= 0x7FFF;
val = plugin[i++];
while (n--) {
writeRegister(addr, val);
}
} else { /* Copy run, copy n samples */
while (n--) {
val = plugin[i++];
writeRegister(addr, val);
}
}
}
}

/**
* Load the latest generic firmware patch
*/
void VS1053::loadDefaultVs1053Patches() {
loadUserCode(PATCHES);
};
13 changes: 11 additions & 2 deletions src/VS1053.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
#include <SPI.h>
#include "ConsoleLogger.h"

#include "patches/vs1053b-patches.plg"

class VS1053 {
private:
uint8_t cs_pin; // Pin where CS line is connected
Expand Down Expand Up @@ -168,8 +170,15 @@ class VS1053 {
void clearDecodedTime();

// Writes to VS10xx's SCI (serial command interface) SPI bus.
// A low level method which helps in loading firmware patches in user code.
void write_register(uint8_t _reg, uint16_t _value) const;
// A low level method which lets users access the internals of the VS1053.
void writeRegister(uint8_t _reg, uint16_t _value) const;

// Load a patch or plugin to fix bugs and/or extend functionality.
// For more info about patches see http://www.vlsi.fi/en/support/software/vs10xxpatches.html
void loadUserCode(const unsigned short* plugin);

// Loads the latest generic firmware patch.
void loadDefaultVs1053Patches();
};

#endif
Loading