Skip to content

Commit bae6fed

Browse files
Load VLSI firmware patches. (#69)
Adding an extension by @CelliesProjects for dealing with vs1053 Firmware patches (binary patch files that can easily be loaded to the memory of VS10XX by a microcontroller to fix known firmware bugs): * enable a possibility for using patches/plugins, * load a default patch, * include the latest available patches from http://www.vlsi.fi/en/support/software/vs10xxpatches.html * update example code and documentation, * adjust a functionality for low-level `writeRegister`.
1 parent 9e4e14a commit bae6fed

File tree

10 files changed

+4433
-24
lines changed

10 files changed

+4433
-24
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ Then initialize the player and use as in following example:
5151

5252
```
5353
player.begin();
54+
player.loadDefaultVs1053Patches();
5455
player.setVolume(VOLUME);
5556
player.switchToMp3Mode();
5657
player.playChunk(sampleMp3, sizeof(sampleMp3));

examples/Mp3PlayerDemo/Mp3PlayerDemo.ino

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ void setup() {
7777
Serial.println("Hello VS1053!\n");
7878
// initialize a player
7979
player.begin();
80+
player.loadDefaultVs1053Patches();
8081
player.switchToMp3Mode(); // optional, some boards require this
8182
player.setVolume(VOLUME);
8283
}

examples/WebRadioDemo/WebRadioDemo.ino

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
44
Copyright (C) 2018 Vince Gellár (github.com/vincegellar)
55
Licensed under GNU GPL v3
6-
6+
77
Wiring:
88
--------------------------------
99
| VS1053 | ESP8266 | ESP32 |
@@ -101,6 +101,7 @@ void setup() {
101101
SPI.begin();
102102

103103
player.begin();
104+
player.loadDefaultVs1053Patches();
104105
player.switchToMp3Mode();
105106
player.setVolume(VOLUME);
106107

src/VS1053.cpp

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ uint16_t VS1053::read_register(uint8_t _reg) const {
5050
return result;
5151
}
5252

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

9999
void VS1053::wram_write(uint16_t address, uint16_t data) {
100-
write_register(SCI_WRAMADDR, address);
101-
write_register(SCI_WRAM, data);
100+
writeRegister(SCI_WRAMADDR, address);
101+
writeRegister(SCI_WRAM, data);
102102
}
103103

104104
uint16_t VS1053::wram_read(uint16_t address) {
105-
write_register(SCI_WRAMADDR, address); // Start reading from WRAM
105+
writeRegister(SCI_WRAMADDR, address); // Start reading from WRAM
106106
return read_register(SCI_WRAM); // Read back result
107107
}
108108

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

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

207-
write_register(SCI_VOL, (valueL << 8) | valueR); // Volume left and right
207+
writeRegister(SCI_VOL, (valueL << 8) | valueR); // Volume left and right
208208
}
209209

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

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

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

267267
void VS1053::softReset() {
268268
LOG("Performing soft-reset\n");
269-
write_register(SCI_MODE, _BV(SM_SDINEW) | _BV(SM_RESET));
269+
writeRegister(SCI_MODE, _BV(SM_SDINEW) | _BV(SM_RESET));
270270
delay(10);
271271
await_data_request();
272272
}
@@ -347,20 +347,51 @@ uint16_t VS1053::getDecodedTime() {
347347
* byteRate calculation.
348348
*/
349349
void VS1053::clearDecodedTime() {
350-
write_register(SCI_DECODE_TIME, 0x00);
351-
write_register(SCI_DECODE_TIME, 0x00);
350+
writeRegister(SCI_DECODE_TIME, 0x00);
351+
writeRegister(SCI_DECODE_TIME, 0x00);
352352
}
353353

354354
/**
355355
* Fine tune the data rate
356356
*/
357357
void VS1053::adjustRate(long ppm2) {
358-
write_register(SCI_WRAMADDR, 0x1e07);
359-
write_register(SCI_WRAM, ppm2);
360-
write_register(SCI_WRAM, ppm2 >> 16);
358+
writeRegister(SCI_WRAMADDR, 0x1e07);
359+
writeRegister(SCI_WRAM, ppm2);
360+
writeRegister(SCI_WRAM, ppm2 >> 16);
361361
// oldClock4KHz = 0 forces adjustment calculation when rate checked.
362-
write_register(SCI_WRAMADDR, 0x5b1c);
363-
write_register(SCI_WRAM, 0);
362+
writeRegister(SCI_WRAMADDR, 0x5b1c);
363+
writeRegister(SCI_WRAM, 0);
364364
// Write to AUDATA or CLOCKF checks rate and recalculates adjustment.
365-
write_register(SCI_AUDATA, read_register(SCI_AUDATA));
366-
}
365+
writeRegister(SCI_AUDATA, read_register(SCI_AUDATA));
366+
}
367+
368+
/**
369+
* Load a patch or plugin
370+
*/
371+
void VS1053::loadUserCode(const unsigned short* plugin) {
372+
int i = 0;
373+
while (i<sizeof(plugin)/sizeof(plugin[0])) {
374+
unsigned short addr, n, val;
375+
addr = plugin[i++];
376+
n = plugin[i++];
377+
if (n & 0x8000U) { /* RLE run, replicate n samples */
378+
n &= 0x7FFF;
379+
val = plugin[i++];
380+
while (n--) {
381+
writeRegister(addr, val);
382+
}
383+
} else { /* Copy run, copy n samples */
384+
while (n--) {
385+
val = plugin[i++];
386+
writeRegister(addr, val);
387+
}
388+
}
389+
}
390+
}
391+
392+
/**
393+
* Load the latest generic firmware patch
394+
*/
395+
void VS1053::loadDefaultVs1053Patches() {
396+
loadUserCode(PATCHES);
397+
};

src/VS1053.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
#include <SPI.h>
3939
#include "ConsoleLogger.h"
4040

41+
#include "patches/vs1053b-patches.plg"
42+
4143
class VS1053 {
4244
private:
4345
uint8_t cs_pin; // Pin where CS line is connected
@@ -168,8 +170,15 @@ class VS1053 {
168170
void clearDecodedTime();
169171

170172
// Writes to VS10xx's SCI (serial command interface) SPI bus.
171-
// A low level method which helps in loading firmware patches in user code.
172-
void write_register(uint8_t _reg, uint16_t _value) const;
173+
// A low level method which lets users access the internals of the VS1053.
174+
void writeRegister(uint8_t _reg, uint16_t _value) const;
175+
176+
// Load a patch or plugin to fix bugs and/or extend functionality.
177+
// For more info about patches see http://www.vlsi.fi/en/support/software/vs10xxpatches.html
178+
void loadUserCode(const unsigned short* plugin);
179+
180+
// Loads the latest generic firmware patch.
181+
void loadDefaultVs1053Patches();
173182
};
174183

175184
#endif

0 commit comments

Comments
 (0)