PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Adafruit_VS1053.cpp 17KB

3 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  1. /***************************************************
  2. This is a library for the Adafruit VS1053 Codec Breakout
  3. Designed specifically to work with the Adafruit VS1053 Codec Breakout
  4. ----> https://www.adafruit.com/products/1381
  5. Adafruit invests time and resources providing this open source code,
  6. please support Adafruit and open-source hardware by purchasing
  7. products from Adafruit!
  8. Written by Limor Fried/Ladyada for Adafruit Industries.
  9. BSD license, all text above must be included in any redistribution
  10. ****************************************************/
  11. #include <Adafruit_VS1053.h>
  12. #include <SD.h>
  13. static Adafruit_VS1053_FilePlayer *myself;
  14. #if defined(__AVR__)
  15. SIGNAL(TIMER0_COMPA_vect) {
  16. myself->feedBuffer();
  17. }
  18. #endif
  19. static void feeder(void) {
  20. myself->feedBuffer();
  21. }
  22. #define VS1053_CONTROL_SPI_SETTING SPISettings(250000, MSBFIRST, SPI_MODE0)
  23. #define VS1053_DATA_SPI_SETTING SPISettings(8000000, MSBFIRST, SPI_MODE0)
  24. static const uint8_t dreqinttable[] = {
  25. #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined (__AVR_ATmega328__) || defined(__AVR_ATmega8__)
  26. 2, 0,
  27. 3, 1,
  28. #elif defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__)
  29. 2, 0,
  30. 3, 1,
  31. 21, 2,
  32. 20, 3,
  33. 19, 4,
  34. 18, 5,
  35. #elif defined(__AVR_ATmega32U4__) && defined(CORE_TEENSY)
  36. 5, 0,
  37. 6, 1,
  38. 7, 2,
  39. 8, 3,
  40. #elif defined(__AVR_AT90USB1286__) && defined(CORE_TEENSY)
  41. 0, 0,
  42. 1, 1,
  43. 2, 2,
  44. 3, 3,
  45. 36, 4,
  46. 37, 5,
  47. 18, 6,
  48. 19, 7,
  49. #elif defined(__arm__) && defined(CORE_TEENSY)
  50. 0, 0, 1, 1, 2, 2, 3, 3, 4, 4,
  51. 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
  52. 10, 10, 11, 11, 12, 12, 13, 13, 14, 14,
  53. 15, 15, 16, 16, 17, 17, 18, 18, 19, 19,
  54. 20, 20, 21, 21, 22, 22, 23, 23, 24, 24,
  55. 25, 25, 26, 26, 27, 27, 28, 28, 29, 29,
  56. 30, 30, 31, 31, 32, 32, 33, 33,
  57. #elif defined(__AVR_ATmega32U4__)
  58. 3, 0,
  59. 2, 1,
  60. 0, 2,
  61. 1, 3,
  62. 7, 4,
  63. #endif
  64. };
  65. boolean Adafruit_VS1053_FilePlayer::useInterrupt(uint8_t type) {
  66. myself = this; // oy vey
  67. if (type == VS1053_FILEPLAYER_TIMER0_INT) {
  68. #if defined(__AVR__)
  69. OCR0A = 0xAF;
  70. TIMSK0 |= _BV(OCIE0A);
  71. return true;
  72. #elif defined(__arm__) && defined(CORE_TEENSY)
  73. IntervalTimer *t = new IntervalTimer();
  74. return (t && t->begin(feeder, 1024)) ? true : false;
  75. #else
  76. return false;
  77. #endif
  78. }
  79. if (type == VS1053_FILEPLAYER_PIN_INT) {
  80. for (uint8_t i=0; i<sizeof(dreqinttable); i+=2) {
  81. //Serial.println(dreqinttable[i]);
  82. if (_dreq == dreqinttable[i]) {
  83. #ifdef SPI_HAS_TRANSACTION
  84. SPI.usingInterrupt(dreqinttable[i+1]);
  85. #endif
  86. attachInterrupt(dreqinttable[i+1], feeder, CHANGE);
  87. return true;
  88. }
  89. }
  90. }
  91. return false;
  92. }
  93. Adafruit_VS1053_FilePlayer::Adafruit_VS1053_FilePlayer(
  94. int8_t rst, int8_t cs, int8_t dcs, int8_t dreq,
  95. int8_t cardcs)
  96. : Adafruit_VS1053(rst, cs, dcs, dreq) {
  97. playingMusic = false;
  98. // Set the card to be disabled while we get the VS1053 up
  99. pinMode(_cardCS, OUTPUT);
  100. digitalWrite(_cardCS, HIGH);
  101. }
  102. Adafruit_VS1053_FilePlayer::Adafruit_VS1053_FilePlayer(
  103. int8_t cs, int8_t dcs, int8_t dreq,
  104. int8_t cardcs)
  105. : Adafruit_VS1053(-1, cs, dcs, dreq) {
  106. playingMusic = false;
  107. // Set the card to be disabled while we get the VS1053 up
  108. pinMode(_cardCS, OUTPUT);
  109. digitalWrite(_cardCS, HIGH);
  110. }
  111. Adafruit_VS1053_FilePlayer::Adafruit_VS1053_FilePlayer(
  112. int8_t mosi, int8_t miso, int8_t clk,
  113. int8_t rst, int8_t cs, int8_t dcs, int8_t dreq,
  114. int8_t cardcs)
  115. : Adafruit_VS1053(mosi, miso, clk, rst, cs, dcs, dreq) {
  116. playingMusic = false;
  117. // Set the card to be disabled while we get the VS1053 up
  118. pinMode(_cardCS, OUTPUT);
  119. digitalWrite(_cardCS, HIGH);
  120. }
  121. boolean Adafruit_VS1053_FilePlayer::begin(void) {
  122. uint8_t v = Adafruit_VS1053::begin();
  123. //dumpRegs();
  124. //Serial.print("Version = "); Serial.println(v);
  125. return (v == 4);
  126. }
  127. boolean Adafruit_VS1053_FilePlayer::playFullFile(const char *trackname) {
  128. if (! startPlayingFile(trackname)) return false;
  129. while (playingMusic) {
  130. // twiddle thumbs
  131. feedBuffer();
  132. }
  133. // music file finished!
  134. return true;
  135. }
  136. void Adafruit_VS1053_FilePlayer::stopPlaying(void) {
  137. // wrap it up!
  138. playingMusic = false;
  139. currentTrack.close();
  140. }
  141. void Adafruit_VS1053_FilePlayer::pausePlaying(boolean pause) {
  142. if (pause)
  143. playingMusic = false;
  144. else {
  145. playingMusic = true;
  146. feedBuffer();
  147. }
  148. }
  149. boolean Adafruit_VS1053_FilePlayer::paused(void) {
  150. return (!playingMusic && currentTrack);
  151. }
  152. boolean Adafruit_VS1053_FilePlayer::stopped(void) {
  153. return (!playingMusic && !currentTrack);
  154. }
  155. boolean Adafruit_VS1053_FilePlayer::startPlayingFile(const char *trackname) {
  156. currentTrack = SD.open(trackname);
  157. if (!currentTrack) {
  158. return false;
  159. }
  160. playingMusic = true;
  161. // wait till its ready for data
  162. while (! readyForData() );
  163. // fill it up!
  164. while (playingMusic && readyForData())
  165. feedBuffer();
  166. // Serial.println("Ready");
  167. return true;
  168. }
  169. void Adafruit_VS1053_FilePlayer::feedBuffer(void) {
  170. static uint8_t running = 0;
  171. uint8_t sregsave;
  172. // Do not allow 2 copies of this code to run concurrently.
  173. // If an interrupt causes feedBuffer() to run while another
  174. // copy of feedBuffer() is already running in the main
  175. // program, havoc can occur. "running" detects this state
  176. // and safely returns.
  177. sregsave = SREG;
  178. cli();
  179. if (running) {
  180. SREG = sregsave;
  181. return; // return safely, before touching hardware! :-)
  182. } else {
  183. running = 1;
  184. SREG = sregsave;
  185. }
  186. if (! playingMusic) {
  187. running = 0;
  188. return; // paused or stopped
  189. }
  190. if (! currentTrack) {
  191. running = 0;
  192. return;
  193. }
  194. if (! readyForData()) {
  195. running = 0;
  196. return;
  197. }
  198. // Feed the hungry buffer! :)
  199. while (readyForData()) {
  200. //UDR0 = '.';
  201. // Read some audio data from the SD card file
  202. int bytesread = currentTrack.read(mp3buffer, VS1053_DATABUFFERLEN);
  203. if (bytesread == 0) {
  204. // must be at the end of the file, wrap it up!
  205. playingMusic = false;
  206. currentTrack.close();
  207. running = 0;
  208. return;
  209. }
  210. playData(mp3buffer, bytesread);
  211. }
  212. running = 0;
  213. return;
  214. }
  215. /***************************************************************/
  216. /* VS1053 'low level' interface */
  217. static volatile uint8_t *clkportreg, *misoportreg, *mosiportreg;
  218. static uint8_t clkpin, misopin, mosipin;
  219. Adafruit_VS1053::Adafruit_VS1053(int8_t mosi, int8_t miso, int8_t clk,
  220. int8_t rst, int8_t cs, int8_t dcs, int8_t dreq) {
  221. _mosi = mosi;
  222. _miso = miso;
  223. _clk = clk;
  224. _reset = rst;
  225. _cs = cs;
  226. _dcs = dcs;
  227. _dreq = dreq;
  228. useHardwareSPI = false;
  229. clkportreg = portOutputRegister(digitalPinToPort(_clk));
  230. clkpin = digitalPinToBitMask(_clk);
  231. misoportreg = portInputRegister(digitalPinToPort(_miso));
  232. misopin = digitalPinToBitMask(_miso);
  233. mosiportreg = portOutputRegister(digitalPinToPort(_mosi));
  234. mosipin = digitalPinToBitMask(_mosi);
  235. }
  236. Adafruit_VS1053::Adafruit_VS1053(int8_t rst, int8_t cs, int8_t dcs, int8_t dreq) {
  237. _mosi = 0;
  238. _miso = 0;
  239. _clk = 0;
  240. useHardwareSPI = true;
  241. _reset = rst;
  242. _cs = cs;
  243. _dcs = dcs;
  244. _dreq = dreq;
  245. }
  246. void Adafruit_VS1053::applyPatch(const uint16_t *patch, uint16_t patchsize) {
  247. uint16_t i = 0;
  248. // Serial.print("Patch size: "); Serial.println(patchsize);
  249. while ( i < patchsize ) {
  250. uint16_t addr, n, val;
  251. addr = pgm_read_word(patch++);
  252. n = pgm_read_word(patch++);
  253. i += 2;
  254. //Serial.println(addr, HEX);
  255. if (n & 0x8000U) { // RLE run, replicate n samples
  256. n &= 0x7FFF;
  257. val = pgm_read_word(patch++);
  258. i++;
  259. while (n--) {
  260. sciWrite(addr, val);
  261. }
  262. } else { // Copy run, copy n samples
  263. while (n--) {
  264. val = pgm_read_word(patch++);
  265. i++;
  266. sciWrite(addr, val);
  267. }
  268. }
  269. }
  270. }
  271. uint16_t Adafruit_VS1053::loadPlugin(char *plugname) {
  272. File plugin = SD.open(plugname);
  273. if (!plugin) {
  274. Serial.println("Couldn't open the plugin file");
  275. Serial.println(plugin);
  276. return 0xFFFF;
  277. }
  278. if ((plugin.read() != 'P') ||
  279. (plugin.read() != '&') ||
  280. (plugin.read() != 'H'))
  281. return 0xFFFF;
  282. uint16_t type;
  283. // Serial.print("Patch size: "); Serial.println(patchsize);
  284. while ((type = plugin.read()) >= 0) {
  285. uint16_t offsets[] = {0x8000UL, 0x0, 0x4000UL};
  286. uint16_t addr, len;
  287. //Serial.print("type: "); Serial.println(type, HEX);
  288. if (type >= 4) {
  289. plugin.close();
  290. return 0xFFFF;
  291. }
  292. len = plugin.read(); len <<= 8;
  293. len |= plugin.read() & ~1;
  294. addr = plugin.read(); addr <<= 8;
  295. addr |= plugin.read();
  296. //Serial.print("len: "); Serial.print(len);
  297. //Serial.print(" addr: $"); Serial.println(addr, HEX);
  298. if (type == 3) {
  299. // execute rec!
  300. plugin.close();
  301. return addr;
  302. }
  303. // set address
  304. sciWrite(VS1053_REG_WRAMADDR, addr + offsets[type]);
  305. // write data
  306. do {
  307. uint16_t data;
  308. data = plugin.read(); data <<= 8;
  309. data |= plugin.read();
  310. sciWrite(VS1053_REG_WRAM, data);
  311. } while ((len -=2));
  312. }
  313. plugin.close();
  314. return 0xFFFF;
  315. }
  316. boolean Adafruit_VS1053::readyForData(void) {
  317. return digitalRead(_dreq);
  318. }
  319. void Adafruit_VS1053::playData(uint8_t *buffer, uint8_t buffsiz) {
  320. #ifdef SPI_HAS_TRANSACTION
  321. if (useHardwareSPI) SPI.beginTransaction(VS1053_DATA_SPI_SETTING);
  322. #endif
  323. digitalWrite(_dcs, LOW);
  324. for (uint8_t i=0; i<buffsiz; i++) {
  325. spiwrite(buffer[i]);
  326. }
  327. digitalWrite(_dcs, HIGH);
  328. #ifdef SPI_HAS_TRANSACTION
  329. if (useHardwareSPI) SPI.endTransaction();
  330. #endif
  331. }
  332. void Adafruit_VS1053::setVolume(uint8_t left, uint8_t right) {
  333. uint16_t v;
  334. v = left;
  335. v <<= 8;
  336. v |= right;
  337. cli();
  338. sciWrite(VS1053_REG_VOLUME, v);
  339. sei();
  340. }
  341. uint16_t Adafruit_VS1053::decodeTime() {
  342. cli();
  343. uint16_t t = sciRead(VS1053_REG_DECODETIME);
  344. sei();
  345. return t;
  346. }
  347. void Adafruit_VS1053::softReset(void) {
  348. sciWrite(VS1053_REG_MODE, VS1053_MODE_SM_SDINEW | VS1053_MODE_SM_RESET);
  349. delay(100);
  350. }
  351. void Adafruit_VS1053::reset() {
  352. // TODO: http://www.vlsi.fi/player_vs1011_1002_1003/modularplayer/vs10xx_8c.html#a3
  353. // hardware reset
  354. if (_reset >= 0) {
  355. digitalWrite(_reset, LOW);
  356. delay(100);
  357. digitalWrite(_reset, HIGH);
  358. }
  359. digitalWrite(_cs, HIGH);
  360. digitalWrite(_dcs, HIGH);
  361. delay(100);
  362. softReset();
  363. delay(100);
  364. sciWrite(VS1053_REG_CLOCKF, 0x6000);
  365. setVolume(40, 40);
  366. }
  367. uint8_t Adafruit_VS1053::begin(void) {
  368. if (_reset >= 0) {
  369. pinMode(_reset, OUTPUT);
  370. digitalWrite(_reset, LOW);
  371. }
  372. pinMode(_cs, OUTPUT);
  373. digitalWrite(_cs, HIGH);
  374. pinMode(_dcs, OUTPUT);
  375. digitalWrite(_dcs, HIGH);
  376. pinMode(_dreq, INPUT);
  377. if (! useHardwareSPI) {
  378. pinMode(_mosi, OUTPUT);
  379. pinMode(_clk, OUTPUT);
  380. pinMode(_miso, INPUT);
  381. } else {
  382. SPI.begin();
  383. SPI.setDataMode(SPI_MODE0);
  384. SPI.setBitOrder(MSBFIRST);
  385. SPI.setClockDivider(SPI_CLOCK_DIV128);
  386. }
  387. reset();
  388. return (sciRead(VS1053_REG_STATUS) >> 4) & 0x0F;
  389. }
  390. void Adafruit_VS1053::dumpRegs(void) {
  391. Serial.print("Mode = 0x"); Serial.println(sciRead(VS1053_REG_MODE), HEX);
  392. Serial.print("Stat = 0x"); Serial.println(sciRead(VS1053_REG_STATUS), HEX);
  393. Serial.print("ClkF = 0x"); Serial.println(sciRead(VS1053_REG_CLOCKF), HEX);
  394. Serial.print("Vol. = 0x"); Serial.println(sciRead(VS1053_REG_VOLUME), HEX);
  395. }
  396. uint16_t Adafruit_VS1053::recordedWordsWaiting(void) {
  397. return sciRead(VS1053_REG_HDAT1);
  398. }
  399. uint16_t Adafruit_VS1053::recordedReadWord(void) {
  400. return sciRead(VS1053_REG_HDAT0);
  401. }
  402. boolean Adafruit_VS1053::prepareRecordOgg(char *plugname) {
  403. sciWrite(VS1053_REG_CLOCKF, 0xC000); // set max clock
  404. delay(1); while (! readyForData() );
  405. sciWrite(VS1053_REG_BASS, 0); // clear Bass
  406. softReset();
  407. delay(1); while (! readyForData() );
  408. sciWrite(VS1053_SCI_AIADDR, 0);
  409. // disable all interrupts except SCI
  410. sciWrite(VS1053_REG_WRAMADDR, VS1053_INT_ENABLE);
  411. sciWrite(VS1053_REG_WRAM, 0x02);
  412. int pluginStartAddr = loadPlugin(plugname);
  413. if (pluginStartAddr == 0xFFFF) return false;
  414. Serial.print("Plugin at $"); Serial.println(pluginStartAddr, HEX);
  415. if (pluginStartAddr != 0x34) return false;
  416. return true;
  417. }
  418. void Adafruit_VS1053::stopRecordOgg(void) {
  419. sciWrite(VS1053_SCI_AICTRL3, 1);
  420. }
  421. void Adafruit_VS1053::startRecordOgg(boolean mic) {
  422. /* Set VS1053 mode bits as instructed in the VS1053b Ogg Vorbis Encoder
  423. manual. Note: for microphone input, leave SMF_LINE1 unset! */
  424. if (mic) {
  425. sciWrite(VS1053_REG_MODE, VS1053_MODE_SM_ADPCM | VS1053_MODE_SM_SDINEW);
  426. } else {
  427. sciWrite(VS1053_REG_MODE, VS1053_MODE_SM_LINE1 |
  428. VS1053_MODE_SM_ADPCM | VS1053_MODE_SM_SDINEW);
  429. }
  430. sciWrite(VS1053_SCI_AICTRL0, 1024);
  431. /* Rec level: 1024 = 1. If 0, use AGC */
  432. sciWrite(VS1053_SCI_AICTRL1, 1024);
  433. /* Maximum AGC level: 1024 = 1. Only used if SCI_AICTRL1 is set to 0. */
  434. sciWrite(VS1053_SCI_AICTRL2, 0);
  435. /* Miscellaneous bits that also must be set before recording. */
  436. sciWrite(VS1053_SCI_AICTRL3, 0);
  437. sciWrite(VS1053_SCI_AIADDR, 0x34);
  438. delay(1); while (! readyForData() );
  439. }
  440. void Adafruit_VS1053::GPIO_pinMode(uint8_t i, uint8_t dir) {
  441. if (i > 7) return;
  442. sciWrite(VS1053_REG_WRAMADDR, VS1053_GPIO_DDR);
  443. uint16_t ddr = sciRead(VS1053_REG_WRAM);
  444. if (dir == INPUT)
  445. ddr &= ~_BV(i);
  446. if (dir == OUTPUT)
  447. ddr |= _BV(i);
  448. sciWrite(VS1053_REG_WRAMADDR, VS1053_GPIO_DDR);
  449. sciWrite(VS1053_REG_WRAM, ddr);
  450. }
  451. void Adafruit_VS1053::GPIO_digitalWrite(uint8_t val) {
  452. sciWrite(VS1053_REG_WRAMADDR, VS1053_GPIO_ODATA);
  453. sciWrite(VS1053_REG_WRAM, val);
  454. }
  455. void Adafruit_VS1053::GPIO_digitalWrite(uint8_t i, uint8_t val) {
  456. if (i > 7) return;
  457. sciWrite(VS1053_REG_WRAMADDR, VS1053_GPIO_ODATA);
  458. uint16_t pins = sciRead(VS1053_REG_WRAM);
  459. if (val == LOW)
  460. pins &= ~_BV(i);
  461. if (val == HIGH)
  462. pins |= _BV(i);
  463. sciWrite(VS1053_REG_WRAMADDR, VS1053_GPIO_ODATA);
  464. sciWrite(VS1053_REG_WRAM, pins);
  465. }
  466. uint16_t Adafruit_VS1053::GPIO_digitalRead(void) {
  467. sciWrite(VS1053_REG_WRAMADDR, VS1053_GPIO_IDATA);
  468. return sciRead(VS1053_REG_WRAM) & 0xFF;
  469. }
  470. boolean Adafruit_VS1053::GPIO_digitalRead(uint8_t i) {
  471. if (i > 7) return 0;
  472. sciWrite(VS1053_REG_WRAMADDR, VS1053_GPIO_IDATA);
  473. uint16_t val = sciRead(VS1053_REG_WRAM);
  474. if (val & _BV(i)) return true;
  475. return false;
  476. }
  477. uint16_t Adafruit_VS1053::sciRead(uint8_t addr) {
  478. uint16_t data;
  479. #ifdef SPI_HAS_TRANSACTION
  480. if (useHardwareSPI) SPI.beginTransaction(VS1053_CONTROL_SPI_SETTING);
  481. #endif
  482. digitalWrite(_cs, LOW);
  483. spiwrite(VS1053_SCI_READ);
  484. spiwrite(addr);
  485. delayMicroseconds(10);
  486. data = spiread();
  487. data <<= 8;
  488. data |= spiread();
  489. digitalWrite(_cs, HIGH);
  490. #ifdef SPI_HAS_TRANSACTION
  491. if (useHardwareSPI) SPI.endTransaction();
  492. #endif
  493. return data;
  494. }
  495. void Adafruit_VS1053::sciWrite(uint8_t addr, uint16_t data) {
  496. #ifdef SPI_HAS_TRANSACTION
  497. if (useHardwareSPI) SPI.beginTransaction(VS1053_CONTROL_SPI_SETTING);
  498. #endif
  499. digitalWrite(_cs, LOW);
  500. spiwrite(VS1053_SCI_WRITE);
  501. spiwrite(addr);
  502. spiwrite(data >> 8);
  503. spiwrite(data & 0xFF);
  504. digitalWrite(_cs, HIGH);
  505. #ifdef SPI_HAS_TRANSACTION
  506. if (useHardwareSPI) SPI.endTransaction();
  507. #endif
  508. }
  509. uint8_t Adafruit_VS1053::spiread(void)
  510. {
  511. int8_t i, x;
  512. x = 0;
  513. // MSB first, clock low when inactive (CPOL 0), data valid on leading edge (CPHA 0)
  514. // Make sure clock starts low
  515. if (useHardwareSPI) {
  516. x = SPI.transfer(0x00);
  517. } else {
  518. for (i=7; i>=0; i--) {
  519. if ((*misoportreg) & misopin)
  520. x |= (1<<i);
  521. *clkportreg |= clkpin;
  522. *clkportreg &= ~clkpin;
  523. // asm("nop; nop");
  524. }
  525. // Make sure clock ends low
  526. *clkportreg &= ~clkpin;
  527. }
  528. return x;
  529. }
  530. void Adafruit_VS1053::spiwrite(uint8_t c)
  531. {
  532. // MSB first, clock low when inactive (CPOL 0), data valid on leading edge (CPHA 0)
  533. // Make sure clock starts low
  534. if (useHardwareSPI) {
  535. SPI.transfer(c);
  536. } else {
  537. for (int8_t i=7; i>=0; i--) {
  538. *clkportreg &= ~clkpin;
  539. if (c & (1<<i)) {
  540. *mosiportreg |= mosipin;
  541. } else {
  542. *mosiportreg &= ~mosipin;
  543. }
  544. *clkportreg |= clkpin;
  545. }
  546. *clkportreg &= ~clkpin; // Make sure clock ends low
  547. }
  548. }
  549. void Adafruit_VS1053::sineTest(uint8_t n, uint16_t ms) {
  550. reset();
  551. uint16_t mode = sciRead(VS1053_REG_MODE);
  552. mode |= 0x0020;
  553. sciWrite(VS1053_REG_MODE, mode);
  554. while (!digitalRead(_dreq));
  555. // delay(10);
  556. #ifdef SPI_HAS_TRANSACTION
  557. if (useHardwareSPI) SPI.beginTransaction(VS1053_DATA_SPI_SETTING);
  558. #endif
  559. digitalWrite(_dcs, LOW);
  560. spiwrite(0x53);
  561. spiwrite(0xEF);
  562. spiwrite(0x6E);
  563. spiwrite(n);
  564. spiwrite(0x00);
  565. spiwrite(0x00);
  566. spiwrite(0x00);
  567. spiwrite(0x00);
  568. digitalWrite(_dcs, HIGH);
  569. #ifdef SPI_HAS_TRANSACTION
  570. if (useHardwareSPI) SPI.endTransaction();
  571. #endif
  572. delay(ms);
  573. #ifdef SPI_HAS_TRANSACTION
  574. if (useHardwareSPI) SPI.beginTransaction(VS1053_DATA_SPI_SETTING);
  575. #endif
  576. digitalWrite(_dcs, LOW);
  577. spiwrite(0x45);
  578. spiwrite(0x78);
  579. spiwrite(0x69);
  580. spiwrite(0x74);
  581. spiwrite(0x00);
  582. spiwrite(0x00);
  583. spiwrite(0x00);
  584. spiwrite(0x00);
  585. digitalWrite(_dcs, HIGH);
  586. #ifdef SPI_HAS_TRANSACTION
  587. if (useHardwareSPI) SPI.endTransaction();
  588. #endif
  589. }