void Adafruit_VS1053::applyPatch(const uint16_t *patch, uint16_t patchsize) { uint16_t i = 0; // Serial.print("Patch size: "); Serial.println(patchsize); while ( i < patchsize ) { uint16_t addr, n, val; addr = pgm_read_word(patch++); n = pgm_read_word(patch++); i += 2; //Serial.println(addr, HEX); if (n & 0x8000U) { // RLE run, replicate n samples n &= 0x7FFF; val = pgm_read_word(patch++); i++; while (n--) { sciWrite(addr, val); } } else { // Copy run, copy n samples while (n--) { val = pgm_read_word(patch++); i++; sciWrite(addr, val); } } } }
boolean Adafruit_VS1053_FilePlayer::startPlayingFile(const char *trackname) { // reset playback sciWrite(VS1053_REG_MODE, VS1053_MODE_SM_LINE1 | VS1053_MODE_SM_SDINEW); // resync sciWrite(VS1053_REG_WRAMADDR, 0x1e29); sciWrite(VS1053_REG_WRAM, 0); currentTrack = SD.open(trackname); if (!currentTrack) { return false; } // As explained in datasheet, set twice 0 in REG_DECODETIME to set time back to 0 sciWrite(VS1053_REG_DECODETIME, 0x00); sciWrite(VS1053_REG_DECODETIME, 0x00); playingMusic = true; // wait till its ready for data while (!readyForData()); // fill it up! while (playingMusic && readyForData()) feedBuffer(); // Serial.println("Ready"); return true; }
uint16_t Adafruit_VS1053::loadPlugin(char *plugname) { File plugin = SD.open(plugname); if (!plugin) { Serial.println("Couldn't open the plugin file"); Serial.println(plugin); return 0xFFFF; } if ((plugin.read() != 'P') || (plugin.read() != '&') || (plugin.read() != 'H')) return 0xFFFF; uint16_t type; // Serial.print("Patch size: "); Serial.println(patchsize); while ((type = plugin.read()) >= 0) { uint16_t offsets[] = {0x8000UL, 0x0, 0x4000UL}; uint16_t addr, len; //Serial.print("type: "); Serial.println(type, HEX); if (type >= 4) { plugin.close(); return 0xFFFF; } len = plugin.read(); len <<= 8; len |= plugin.read() & ~1; addr = plugin.read(); addr <<= 8; addr |= plugin.read(); //Serial.print("len: "); Serial.print(len); //Serial.print(" addr: $"); Serial.println(addr, HEX); if (type == 3) { // execute rec! plugin.close(); return addr; } // set address sciWrite(VS1053_REG_WRAMADDR, addr + offsets[type]); // write data do { uint16_t data; data = plugin.read(); data <<= 8; data |= plugin.read(); sciWrite(VS1053_REG_WRAM, data); } while ((len -=2)); } plugin.close(); return 0xFFFF; }
void Adafruit_VS1053::GPIO_pinMode(uint8_t i, uint8_t dir) { if (i > 7) return; sciWrite(VS1053_REG_WRAMADDR, VS1053_GPIO_DDR); uint16_t ddr = sciRead(VS1053_REG_WRAM); if (dir == INPUT) ddr &= ~_BV(i); if (dir == OUTPUT) ddr |= _BV(i); sciWrite(VS1053_REG_WRAMADDR, VS1053_GPIO_DDR); sciWrite(VS1053_REG_WRAM, ddr); }
void Adafruit_VS1053::GPIO_digitalWrite(uint8_t i, uint8_t val) { if (i > 7) return; sciWrite(VS1053_REG_WRAMADDR, VS1053_GPIO_ODATA); uint16_t pins = sciRead(VS1053_REG_WRAM); if (val == LOW) pins &= ~_BV(i); if (val == HIGH) pins |= _BV(i); sciWrite(VS1053_REG_WRAMADDR, VS1053_GPIO_ODATA); sciWrite(VS1053_REG_WRAM, pins); }
void Adafruit_VS1053_FilePlayer::stopSong(void) { // cancel all playback sciWrite(VS1053_REG_MODE, VS1053_MODE_SM_LINE1 | VS1053_MODE_SM_SDINEW | VS1053_MODE_SM_CANCEL); // wrap it up! playingMusic = false; }
boolean Adafruit_VS1053::GPIO_digitalRead(uint8_t i) { if (i > 7) return 0; sciWrite(VS1053_REG_WRAMADDR, VS1053_GPIO_IDATA); uint16_t val = sciRead(VS1053_REG_WRAM); if (val & _BV(i)) return true; return false; }
boolean Adafruit_VS1053_FilePlayer::startPlayingFile(const char *trackname) { // reset playback sciWrite(VS1053_REG_MODE, VS1053_MODE_SM_LINE1 | VS1053_MODE_SM_SDINEW); // resync sciWrite(VS1053_REG_WRAMADDR, 0x1e29); sciWrite(VS1053_REG_WRAM, 0); currentTrack = SD.open(trackname); if (!currentTrack) { return false; } // We know we have a valid file. Check if .mp3 // If so, check for ID3 tag and jump it if present. if (isMP3File(trackname)) { currentTrack.seek(mp3_ID3Jumper(currentTrack)); } // don't let the IRQ get triggered by accident here noInterrupts(); // As explained in datasheet, set twice 0 in REG_DECODETIME to set time back to 0 sciWrite(VS1053_REG_DECODETIME, 0x00); sciWrite(VS1053_REG_DECODETIME, 0x00); playingMusic = true; // wait till its ready for data while (! readyForData() ) { #if defined(ESP8266) yield(); #endif } // fill it up! while (playingMusic && readyForData()) { feedBuffer(); } // ok going forward, we can use the IRQ interrupts(); return true; }
void Adafruit_VS1053::setVolume(uint8_t left, uint8_t right) { uint16_t v; v = left; v <<= 8; v |= right; noInterrupts(); //cli(); sciWrite(VS1053_REG_VOLUME, v); interrupts(); //sei(); }
boolean Adafruit_VS1053::prepareRecordOgg(char *plugname) { sciWrite(VS1053_REG_CLOCKF, 0xC000); // set max clock delay(1); while (! readyForData() ); sciWrite(VS1053_REG_BASS, 0); // clear Bass softReset(); delay(1); while (! readyForData() ); sciWrite(VS1053_SCI_AIADDR, 0); // disable all interrupts except SCI sciWrite(VS1053_REG_WRAMADDR, VS1053_INT_ENABLE); sciWrite(VS1053_REG_WRAM, 0x02); int pluginStartAddr = loadPlugin(plugname); if (pluginStartAddr == 0xFFFF) return false; Serial.print("Plugin at $"); Serial.println(pluginStartAddr, HEX); if (pluginStartAddr != 0x34) return false; return true; }
void Adafruit_VS1053::sineTest(uint8_t n, uint16_t ms) { reset(); uint16_t mode = sciRead(VS1053_REG_MODE); mode |= 0x0020; sciWrite(VS1053_REG_MODE, mode); while (!digitalRead(_dreq)); // delay(10); #ifdef SPI_HAS_TRANSACTION if (useHardwareSPI) SPI.beginTransaction(VS1053_DATA_SPI_SETTING); #endif digitalWrite(_dcs, LOW); spiWrite(0x53); spiWrite(0xEF); spiWrite(0x6E); spiWrite(n); spiWrite(0x00); spiWrite(0x00); spiWrite(0x00); spiWrite(0x00); digitalWrite(_dcs, HIGH); #ifdef SPI_HAS_TRANSACTION if (useHardwareSPI) SPI.endTransaction(); #endif delay(ms); #ifdef SPI_HAS_TRANSACTION if (useHardwareSPI) SPI.beginTransaction(VS1053_DATA_SPI_SETTING); #endif digitalWrite(_dcs, LOW); spiWrite(0x45); spiWrite(0x78); spiWrite(0x69); spiWrite(0x74); spiWrite(0x00); spiWrite(0x00); spiWrite(0x00); spiWrite(0x00); digitalWrite(_dcs, HIGH); #ifdef SPI_HAS_TRANSACTION if (useHardwareSPI) SPI.endTransaction(); #endif }
void Adafruit_VS1053::reset() { // TODO: http://www.vlsi.fi/player_vs1011_1002_1003/modularplayer/vs10xx_8c.html#a3 // hardware reset if (_reset >= 0) { digitalWrite(_reset, LOW); delay(100); digitalWrite(_reset, HIGH); } digitalWrite(_cs, HIGH); digitalWrite(_dcs, HIGH); delay(100); softReset(); delay(100); sciWrite(VS1053_REG_CLOCKF, 0x6000); setVolume(40, 40); }
void Adafruit_VS1053::startRecordOgg(boolean mic) { /* Set VS1053 mode bits as instructed in the VS1053b Ogg Vorbis Encoder manual. Note: for microphone input, leave SMF_LINE1 unset! */ if (mic) { sciWrite(VS1053_REG_MODE, VS1053_MODE_SM_ADPCM | VS1053_MODE_SM_SDINEW); } else { sciWrite(VS1053_REG_MODE, VS1053_MODE_SM_LINE1 | VS1053_MODE_SM_ADPCM | VS1053_MODE_SM_SDINEW); } sciWrite(VS1053_SCI_AICTRL0, 1024); /* Rec level: 1024 = 1. If 0, use AGC */ sciWrite(VS1053_SCI_AICTRL1, 1024); /* Maximum AGC level: 1024 = 1. Only used if SCI_AICTRL1 is set to 0. */ sciWrite(VS1053_SCI_AICTRL2, 0); /* Miscellaneous bits that also must be set before recording. */ sciWrite(VS1053_SCI_AICTRL3, 0); sciWrite(VS1053_SCI_AIADDR, 0x34); delay(1); while (! readyForData() ); }
void Adafruit_VS1053::GPIO_digitalWrite(uint8_t val) { sciWrite(VS1053_REG_WRAMADDR, VS1053_GPIO_ODATA); sciWrite(VS1053_REG_WRAM, val); }
void Adafruit_VS1053::softReset(void) { sciWrite(VS1053_REG_MODE, VS1053_MODE_SM_SDINEW | VS1053_MODE_SM_RESET); delay(100); }
void Adafruit_VS1053::stopPlaying(void) { // cancel all playback sciWrite(VS1053_REG_MODE, VS1053_MODE_SM_LINE1 | VS1053_MODE_SM_SDINEW | VS1053_MODE_SM_CANCEL); }
void Adafruit_VS1053::stopRecordOgg(void) { sciWrite(VS1053_SCI_AICTRL3, 1); }
uint16_t Adafruit_VS1053::GPIO_digitalRead(void) { sciWrite(VS1053_REG_WRAMADDR, VS1053_GPIO_IDATA); return sciRead(VS1053_REG_WRAM) & 0xFF; }