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