Add the RTOS processing. for the Network radio streaming receiver.

Fork of VS1053b by Christian Schmiljun

Committer:
christi_s
Date:
Fri Dec 24 23:52:55 2010 +0000
Revision:
4:cacb5e663fa9
Parent:
3:88a645490529
Child:
5:ead95c0f7800
add buffer handling (ring buffer)
add async writing of audio data to vs1053b
fix interrupt handling

Who changed what in which revision?

UserRevisionLine numberNew contents of line
christi_s 1:ced2c297cc1b 1 /* mbed VLSI VS1053b library
christi_s 1:ced2c297cc1b 2 * Copyright (c) 2010 Christian Schmiljun
christi_s 1:ced2c297cc1b 3 *
christi_s 1:ced2c297cc1b 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
christi_s 1:ced2c297cc1b 5 * of this software and associated documentation files (the "Software"), to deal
christi_s 1:ced2c297cc1b 6 * in the Software without restriction, including without limitation the rights
christi_s 1:ced2c297cc1b 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
christi_s 1:ced2c297cc1b 8 * copies of the Software, and to permit persons to whom the Software is
christi_s 1:ced2c297cc1b 9 * furnished to do so, subject to the following conditions:
christi_s 1:ced2c297cc1b 10 *
christi_s 1:ced2c297cc1b 11 * The above copyright notice and this permission notice shall be included in
christi_s 1:ced2c297cc1b 12 * all copies or substantial portions of the Software.
christi_s 1:ced2c297cc1b 13 *
christi_s 1:ced2c297cc1b 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
christi_s 1:ced2c297cc1b 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
christi_s 1:ced2c297cc1b 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
christi_s 1:ced2c297cc1b 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
christi_s 1:ced2c297cc1b 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
christi_s 1:ced2c297cc1b 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
christi_s 1:ced2c297cc1b 20 * THE SOFTWARE.
christi_s 1:ced2c297cc1b 21 */
christi_s 1:ced2c297cc1b 22
christi_s 1:ced2c297cc1b 23 /* This code based on:
christi_s 1:ced2c297cc1b 24 * mbeduino_MP3_Shield_MP3Player
christi_s 1:ced2c297cc1b 25 * http://mbed.org/users/xshige/programs/mbeduino_MP3_Shield_MP3Player/lgcx63
christi_s 1:ced2c297cc1b 26 * 2010-10-16
christi_s 1:ced2c297cc1b 27 */
christi_s 1:ced2c297cc1b 28
christi_s 0:7728d9c6c487 29 #include "VS1053.h"
christi_s 0:7728d9c6c487 30 #include "mbed.h"
christi_s 0:7728d9c6c487 31
christi_s 0:7728d9c6c487 32 // patch binarys
christi_s 0:7728d9c6c487 33 #include "Patches/VS1053b_patch_1_5.c"
christi_s 0:7728d9c6c487 34 #include "Patches/VS1053b_patch_1_5_flac.c"
christi_s 0:7728d9c6c487 35 #include "Patches/VS1053b_patch_1_4_flac.c"
christi_s 1:ced2c297cc1b 36 #include "Patches/VS1053b_specana_0_9.c"
christi_s 1:ced2c297cc1b 37 #include "Patches/VS1053b_pcm_recorder_0_9.c"
christi_s 0:7728d9c6c487 38
christi_s 0:7728d9c6c487 39
christi_s 4:cacb5e663fa9 40 void test(void)
christi_s 4:cacb5e663fa9 41 {
christi_s 4:cacb5e663fa9 42 // DEBUGOUT("Interupt\r\n");
christi_s 4:cacb5e663fa9 43 }
christi_s 4:cacb5e663fa9 44
christi_s 4:cacb5e663fa9 45
christi_s 0:7728d9c6c487 46 /* ==================================================================
christi_s 0:7728d9c6c487 47 * Constructor
christi_s 0:7728d9c6c487 48 * =================================================================*/
christi_s 0:7728d9c6c487 49 VS1053::VS1053(
christi_s 0:7728d9c6c487 50 PinName mosi, PinName miso, PinName sck, PinName cs, PinName rst,
christi_s 0:7728d9c6c487 51 PinName dreq, PinName dcs)
christi_s 0:7728d9c6c487 52 :
christi_s 0:7728d9c6c487 53 _spi(mosi, miso, sck),
christi_s 0:7728d9c6c487 54 _CS(cs),
christi_s 0:7728d9c6c487 55 _RST(rst),
christi_s 4:cacb5e663fa9 56 _DCS(dcs),
christi_s 4:cacb5e663fa9 57 _DREQ(dreq),
christi_s 4:cacb5e663fa9 58 _DREQ_INTERUPT_IN(dreq)
christi_s 2:5bab956cb59e 59 {
christi_s 1:ced2c297cc1b 60 _volume = DEFAULT_VOLUME;
christi_s 1:ced2c297cc1b 61 _balance = DEFAULT_BALANCE_DIFERENCE_LEFT_RIGHT;
christi_s 2:5bab956cb59e 62 _sb_amplitude = DEFAULT_BASS_AMPLITUDE;
christi_s 2:5bab956cb59e 63 _sb_freqlimit = DEFAULT_BASS_FREQUENCY;
christi_s 2:5bab956cb59e 64 _st_amplitude = DEFAULT_TREBLE_AMPLITUDE;
christi_s 4:cacb5e663fa9 65 _st_freqlimit = DEFAULT_TREBLE_FREQUENCY;
christi_s 4:cacb5e663fa9 66 _DREQ_INTERUPT_IN.mode(PullDown);
christi_s 4:cacb5e663fa9 67 INTERRUPT_HANDLER_DISABLE;
christi_s 4:cacb5e663fa9 68 bufferReset();
christi_s 0:7728d9c6c487 69 }
christi_s 0:7728d9c6c487 70
christi_s 0:7728d9c6c487 71 /*===================================================================
christi_s 0:7728d9c6c487 72 * Functions
christi_s 0:7728d9c6c487 73 *==================================================================*/
christi_s 0:7728d9c6c487 74
christi_s 0:7728d9c6c487 75 void VS1053::cs_low(void) {
christi_s 0:7728d9c6c487 76 _CS = 0;
christi_s 0:7728d9c6c487 77 }
christi_s 0:7728d9c6c487 78 void VS1053::cs_high(void) {
christi_s 0:7728d9c6c487 79 _CS = 1;
christi_s 0:7728d9c6c487 80 }
christi_s 0:7728d9c6c487 81 void VS1053::dcs_low(void) {
christi_s 0:7728d9c6c487 82 _DCS = 0;
christi_s 0:7728d9c6c487 83
christi_s 0:7728d9c6c487 84 }
christi_s 0:7728d9c6c487 85 void VS1053::dcs_high(void) {
christi_s 0:7728d9c6c487 86 _DCS = 1;
christi_s 0:7728d9c6c487 87 }
christi_s 0:7728d9c6c487 88 void VS1053::sci_en(void) { //SCI enable
christi_s 0:7728d9c6c487 89 cs_high();
christi_s 0:7728d9c6c487 90 dcs_high();
christi_s 0:7728d9c6c487 91 cs_low();
christi_s 0:7728d9c6c487 92 }
christi_s 0:7728d9c6c487 93 void VS1053::sci_dis(void) { //SCI disable
christi_s 0:7728d9c6c487 94 cs_high();
christi_s 0:7728d9c6c487 95 }
christi_s 0:7728d9c6c487 96 void VS1053::sdi_en(void) { //SDI enable
christi_s 0:7728d9c6c487 97 dcs_high();
christi_s 0:7728d9c6c487 98 cs_high();
christi_s 0:7728d9c6c487 99 dcs_low();
christi_s 0:7728d9c6c487 100 }
christi_s 0:7728d9c6c487 101 void VS1053::sdi_dis(void) { //SDI disable
christi_s 0:7728d9c6c487 102 dcs_high();
christi_s 0:7728d9c6c487 103 }
christi_s 0:7728d9c6c487 104 void VS1053::reset(void) { //hardware reset
christi_s 4:cacb5e663fa9 105 INTERRUPT_HANDLER_DISABLE;
christi_s 0:7728d9c6c487 106 wait_ms(10);
christi_s 0:7728d9c6c487 107 _RST = 0;
christi_s 0:7728d9c6c487 108 wait_ms(5);
christi_s 0:7728d9c6c487 109 _RST = 1;
christi_s 0:7728d9c6c487 110 wait_ms(10);
christi_s 0:7728d9c6c487 111 }
christi_s 0:7728d9c6c487 112 void VS1053::power_down(void) { //hardware and software reset
christi_s 0:7728d9c6c487 113 cs_low();
christi_s 0:7728d9c6c487 114 reset();
christi_s 0:7728d9c6c487 115 // sci_write(0x00, SM_PDOWN);
christi_s 0:7728d9c6c487 116 sci_write(0x00, 0x10); // tempo
christi_s 0:7728d9c6c487 117 wait(0.01);
christi_s 0:7728d9c6c487 118 reset();
christi_s 0:7728d9c6c487 119 }
christi_s 1:ced2c297cc1b 120 void VS1053::spi_initialise(void) {
christi_s 0:7728d9c6c487 121 _RST = 1; //no reset
christi_s 0:7728d9c6c487 122 _spi.format(8,0); //spi 8bit interface, steady state low
christi_s 0:7728d9c6c487 123 // _spi.frequency(1000000); //rising edge data record, freq. 1Mhz
christi_s 0:7728d9c6c487 124 _spi.frequency(2000000); //rising edge data record, freq. 2Mhz
christi_s 0:7728d9c6c487 125
christi_s 0:7728d9c6c487 126
christi_s 0:7728d9c6c487 127 cs_low();
christi_s 0:7728d9c6c487 128 for (int i=0; i<4; i++) {
christi_s 0:7728d9c6c487 129 _spi.write(0xFF); //clock the chip a bit
christi_s 0:7728d9c6c487 130 }
christi_s 0:7728d9c6c487 131 cs_high();
christi_s 0:7728d9c6c487 132 dcs_high();
christi_s 0:7728d9c6c487 133 wait_us(5);
christi_s 0:7728d9c6c487 134 }
christi_s 0:7728d9c6c487 135 void VS1053::sdi_initialise(void) {
christi_s 1:ced2c297cc1b 136 _spi.frequency(8000000); //set to 8 MHz to make fast transfer
christi_s 0:7728d9c6c487 137 cs_high();
christi_s 0:7728d9c6c487 138 dcs_high();
christi_s 0:7728d9c6c487 139 }
christi_s 0:7728d9c6c487 140 void VS1053::sci_write(unsigned char address, unsigned short int data) {
christi_s 4:cacb5e663fa9 141 // TODO disable all interrupts
christi_s 4:cacb5e663fa9 142 __disable_irq();
christi_s 0:7728d9c6c487 143 sci_en(); //enables SCI/disables SDI
christi_s 0:7728d9c6c487 144
christi_s 0:7728d9c6c487 145 while (!_DREQ); //wait unitl data request is high
christi_s 0:7728d9c6c487 146 _spi.write(0x02); //SCI write
christi_s 0:7728d9c6c487 147 _spi.write(address); //register address
christi_s 0:7728d9c6c487 148 _spi.write((data >> 8) & 0xFF); //write out first half of data word
christi_s 0:7728d9c6c487 149 _spi.write(data & 0xFF); //write out second half of data word
christi_s 0:7728d9c6c487 150
christi_s 0:7728d9c6c487 151 sci_dis(); //enables SDI/disables SCI
christi_s 0:7728d9c6c487 152 wait_us(5);
christi_s 4:cacb5e663fa9 153
christi_s 4:cacb5e663fa9 154 // TODO enable all interrupts
christi_s 4:cacb5e663fa9 155 __enable_irq();
christi_s 0:7728d9c6c487 156 }
christi_s 4:cacb5e663fa9 157 void VS1053::sdi_write(unsigned char datum) {
christi_s 4:cacb5e663fa9 158
christi_s 0:7728d9c6c487 159 sdi_en();
christi_s 0:7728d9c6c487 160
christi_s 0:7728d9c6c487 161 while (!_DREQ);
christi_s 0:7728d9c6c487 162 _spi.write(datum);
christi_s 0:7728d9c6c487 163
christi_s 4:cacb5e663fa9 164 sdi_dis();
christi_s 0:7728d9c6c487 165 }
christi_s 1:ced2c297cc1b 166 unsigned short VS1053::sci_read(unsigned short int address) {
christi_s 4:cacb5e663fa9 167 // TODO disable all interrupts
christi_s 4:cacb5e663fa9 168 __disable_irq();
christi_s 4:cacb5e663fa9 169
christi_s 0:7728d9c6c487 170 cs_low(); //enables SCI/disables SDI
christi_s 0:7728d9c6c487 171
christi_s 0:7728d9c6c487 172 while (!_DREQ); //wait unitl data request is high
christi_s 0:7728d9c6c487 173 _spi.write(0x03); //SCI write
christi_s 0:7728d9c6c487 174 _spi.write(address); //register address
christi_s 0:7728d9c6c487 175 unsigned short int received = _spi.write(0x00); //write out dummy byte
christi_s 0:7728d9c6c487 176 received <<= 8;
christi_s 4:cacb5e663fa9 177 received |= _spi.write(0x00); //write out dummy byte
christi_s 0:7728d9c6c487 178
christi_s 0:7728d9c6c487 179 cs_high(); //enables SDI/disables SCI
christi_s 0:7728d9c6c487 180
christi_s 4:cacb5e663fa9 181 // TODO enable all interrupts
christi_s 4:cacb5e663fa9 182 __enable_irq();
christi_s 0:7728d9c6c487 183 return received; //return received word
christi_s 0:7728d9c6c487 184 }
christi_s 0:7728d9c6c487 185 void VS1053::sine_test_activate(unsigned char wave) {
christi_s 0:7728d9c6c487 186 cs_high(); //enables SDI/disables SCI
christi_s 0:7728d9c6c487 187
christi_s 0:7728d9c6c487 188 while (!_DREQ); //wait unitl data request is high
christi_s 0:7728d9c6c487 189 _spi.write(0x53); //SDI write
christi_s 0:7728d9c6c487 190 _spi.write(0xEF); //SDI write
christi_s 0:7728d9c6c487 191 _spi.write(0x6E); //SDI write
christi_s 0:7728d9c6c487 192 _spi.write(wave); //SDI write
christi_s 0:7728d9c6c487 193 _spi.write(0x00); //filler byte
christi_s 0:7728d9c6c487 194 _spi.write(0x00); //filler byte
christi_s 0:7728d9c6c487 195 _spi.write(0x00); //filler byte
christi_s 0:7728d9c6c487 196 _spi.write(0x00); //filler byte
christi_s 0:7728d9c6c487 197
christi_s 0:7728d9c6c487 198 cs_low(); //enables SCI/disables SDI
christi_s 0:7728d9c6c487 199 }
christi_s 0:7728d9c6c487 200 void VS1053::sine_test_deactivate(void) {
christi_s 0:7728d9c6c487 201 cs_high();
christi_s 0:7728d9c6c487 202
christi_s 0:7728d9c6c487 203 while (!_DREQ);
christi_s 0:7728d9c6c487 204 _spi.write(0x45); //SDI write
christi_s 0:7728d9c6c487 205 _spi.write(0x78); //SDI write
christi_s 0:7728d9c6c487 206 _spi.write(0x69); //SDI write
christi_s 0:7728d9c6c487 207 _spi.write(0x74); //SDI write
christi_s 0:7728d9c6c487 208 _spi.write(0x00); //filler byte
christi_s 0:7728d9c6c487 209 _spi.write(0x00); //filler byte
christi_s 0:7728d9c6c487 210 _spi.write(0x00); //filler byte
christi_s 0:7728d9c6c487 211 _spi.write(0x00); //filler byte
christi_s 0:7728d9c6c487 212 }
christi_s 0:7728d9c6c487 213
christi_s 1:ced2c297cc1b 214 void VS1053::writeStream(unsigned char *array, unsigned int size) {
christi_s 0:7728d9c6c487 215 for (int i=0; i<size; i++) {
christi_s 0:7728d9c6c487 216 sdi_write(array[i]);
christi_s 0:7728d9c6c487 217 }
christi_s 0:7728d9c6c487 218 }
christi_s 0:7728d9c6c487 219
christi_s 0:7728d9c6c487 220 unsigned short int VS1053::wram_read(unsigned short int address) {
christi_s 0:7728d9c6c487 221 unsigned short int tmp1,tmp2;
christi_s 0:7728d9c6c487 222 sci_write(SCI_WRAMADDR,address);
christi_s 0:7728d9c6c487 223 tmp1=sci_read(SCI_WRAM);
christi_s 0:7728d9c6c487 224 sci_write(SCI_WRAMADDR,address);
christi_s 0:7728d9c6c487 225 tmp2=sci_read(SCI_WRAM);
christi_s 0:7728d9c6c487 226 if (tmp1==tmp2) return tmp1;
christi_s 0:7728d9c6c487 227 sci_write(SCI_WRAMADDR,address);
christi_s 0:7728d9c6c487 228 tmp1=sci_read(SCI_WRAM);
christi_s 0:7728d9c6c487 229 if (tmp1==tmp2) return tmp1;
christi_s 0:7728d9c6c487 230 sci_write(SCI_WRAMADDR,address);
christi_s 0:7728d9c6c487 231 tmp1=sci_read(SCI_WRAM);
christi_s 0:7728d9c6c487 232 if (tmp1==tmp2) return tmp1;
christi_s 0:7728d9c6c487 233 return tmp1;
christi_s 0:7728d9c6c487 234 }
christi_s 0:7728d9c6c487 235
christi_s 0:7728d9c6c487 236 void VS1053::wram_write(unsigned short int address, unsigned short int data) {
christi_s 0:7728d9c6c487 237 sci_write(SCI_WRAMADDR,address);
christi_s 0:7728d9c6c487 238 sci_write(SCI_WRAM,data);
christi_s 0:7728d9c6c487 239 return;
christi_s 0:7728d9c6c487 240 }
christi_s 0:7728d9c6c487 241
christi_s 1:ced2c297cc1b 242 void VS1053::setPlaySpeed(unsigned short speed)
christi_s 1:ced2c297cc1b 243 {
christi_s 1:ced2c297cc1b 244 wram_write(para_playSpeed, speed);
christi_s 2:5bab956cb59e 245 DEBUGOUT("VS1053b: Change speed. New speed: %d\r\n", speed);
christi_s 1:ced2c297cc1b 246 }
christi_s 0:7728d9c6c487 247
christi_s 0:7728d9c6c487 248 void VS1053::terminateStream(void) {
christi_s 4:cacb5e663fa9 249 while(bufferCount() > 0)
christi_s 4:cacb5e663fa9 250 ;
christi_s 4:cacb5e663fa9 251 DEBUGOUT("VS1053b: Song terminating..\r\n");
christi_s 1:ced2c297cc1b 252 // send at least 2052 bytes of endFillByte[7:0].
christi_s 1:ced2c297cc1b 253 // read endFillByte (0 .. 15) from wram
christi_s 1:ced2c297cc1b 254 unsigned short endFillByte=wram_read(para_endFillByte);
christi_s 1:ced2c297cc1b 255 // clear endFillByte (8 .. 15)
christi_s 1:ced2c297cc1b 256 endFillByte = endFillByte ^0x00FF;
christi_s 1:ced2c297cc1b 257 for (int n = 0; n < 2052; n++)
christi_s 1:ced2c297cc1b 258 sdi_write(endFillByte);
christi_s 1:ced2c297cc1b 259
christi_s 1:ced2c297cc1b 260 // set SCI MODE bit SM CANCEL
christi_s 1:ced2c297cc1b 261 unsigned short sciModeByte = sci_read(SCI_MODE);
christi_s 1:ced2c297cc1b 262 sciModeByte |= SM_CANCEL;
christi_s 1:ced2c297cc1b 263 sci_write(SCI_MODE, sciModeByte);
christi_s 1:ced2c297cc1b 264
christi_s 1:ced2c297cc1b 265 // send up 2048 bytes of endFillByte[7:0].
christi_s 1:ced2c297cc1b 266 for (int i = 0; i < 64; i++)
christi_s 1:ced2c297cc1b 267 {
christi_s 1:ced2c297cc1b 268 // send at least 32 bytes of endFillByte[7:0]
christi_s 1:ced2c297cc1b 269 for (int n = 0; n < 32; n++)
christi_s 1:ced2c297cc1b 270 sdi_write(endFillByte);
christi_s 1:ced2c297cc1b 271 // read SCI MODE; if SM CANCEL is still set, repeat
christi_s 1:ced2c297cc1b 272 sciModeByte = sci_read(SCI_MODE);
christi_s 1:ced2c297cc1b 273 if ((sciModeByte & SM_CANCEL) == 0x0000)
christi_s 1:ced2c297cc1b 274 {
christi_s 1:ced2c297cc1b 275 break;
christi_s 1:ced2c297cc1b 276 }
christi_s 1:ced2c297cc1b 277 }
christi_s 1:ced2c297cc1b 278
christi_s 1:ced2c297cc1b 279 if ((sciModeByte & SM_CANCEL) == 0x0000)
christi_s 1:ced2c297cc1b 280 {
christi_s 2:5bab956cb59e 281 DEBUGOUT("VS1053b: Song sucessfully sent. Terminating OK\r\n");
christi_s 2:5bab956cb59e 282 DEBUGOUT("VS1053b: SCI MODE = %#x, SM_CANCEL = %#x\r\n", sciModeByte, sciModeByte & SM_CANCEL);
christi_s 1:ced2c297cc1b 283 }
christi_s 1:ced2c297cc1b 284 else
christi_s 1:ced2c297cc1b 285 {
christi_s 2:5bab956cb59e 286 DEBUGOUT("VS1053b: SM CANCEL hasn't cleared after sending 2048 bytes, do software reset\r\n");
christi_s 2:5bab956cb59e 287 DEBUGOUT("VS1053b: SCI MODE = %#x, SM_CANCEL = %#x\r\n", sciModeByte, sciModeByte & SM_CANCEL);
christi_s 1:ced2c297cc1b 288 //TODO: testing
christi_s 1:ced2c297cc1b 289 initialize();
christi_s 1:ced2c297cc1b 290 }
christi_s 0:7728d9c6c487 291 }
christi_s 0:7728d9c6c487 292
christi_s 0:7728d9c6c487 293 void VS1053::write_plugin(const unsigned short *plugin, unsigned int len) {
christi_s 0:7728d9c6c487 294 unsigned int i;
christi_s 0:7728d9c6c487 295 unsigned short addr, n, val;
christi_s 0:7728d9c6c487 296
christi_s 0:7728d9c6c487 297 for (i=0; i<len;) {
christi_s 0:7728d9c6c487 298 addr = plugin[i++];
christi_s 0:7728d9c6c487 299 n = plugin[i++];
christi_s 0:7728d9c6c487 300 if (n & 0x8000U) { //RLE run, replicate n samples
christi_s 0:7728d9c6c487 301 n &= 0x7FFF;
christi_s 0:7728d9c6c487 302 val = plugin[i++];
christi_s 0:7728d9c6c487 303 while (n--) {
christi_s 0:7728d9c6c487 304 sci_write(addr,val);
christi_s 0:7728d9c6c487 305 }
christi_s 0:7728d9c6c487 306 } else { //copy run, copy n sample
christi_s 0:7728d9c6c487 307 while (n--) {
christi_s 0:7728d9c6c487 308 val = plugin[i++];
christi_s 0:7728d9c6c487 309 sci_write(addr,val);
christi_s 0:7728d9c6c487 310 }
christi_s 0:7728d9c6c487 311 }
christi_s 0:7728d9c6c487 312 }
christi_s 0:7728d9c6c487 313
christi_s 0:7728d9c6c487 314 return;
christi_s 0:7728d9c6c487 315 }
christi_s 0:7728d9c6c487 316
christi_s 0:7728d9c6c487 317
christi_s 1:ced2c297cc1b 318 bool VS1053::initialize(void) {
christi_s 0:7728d9c6c487 319 _RST = 1;
christi_s 0:7728d9c6c487 320 cs_high(); //chip disabled
christi_s 1:ced2c297cc1b 321 spi_initialise(); //initialise MBED
christi_s 1:ced2c297cc1b 322
christi_s 1:ced2c297cc1b 323 sci_write(SCI_MODE, (SM_SDINEW+SM_RESET)); // set mode reg.
christi_s 0:7728d9c6c487 324 wait_ms(10);
christi_s 1:ced2c297cc1b 325
christi_s 1:ced2c297cc1b 326 #ifdef DEBUG
christi_s 1:ced2c297cc1b 327 unsigned int info = wram_read(para_chipID_0);
christi_s 2:5bab956cb59e 328 DEBUGOUT("VS1053b: ChipID_0:%04X\r\n", info);
christi_s 1:ced2c297cc1b 329 info = wram_read(para_chipID_1);
christi_s 2:5bab956cb59e 330 DEBUGOUT("VS1053b: ChipID_1:%04X\r\n", info);
christi_s 1:ced2c297cc1b 331 info = wram_read(para_version);
christi_s 2:5bab956cb59e 332 DEBUGOUT("VS1053b: Structure version:%04X\r\n", info);
christi_s 0:7728d9c6c487 333 #endif
christi_s 1:ced2c297cc1b 334
christi_s 0:7728d9c6c487 335 //get chip version, set clock multiplier and load patch
christi_s 1:ced2c297cc1b 336 int i = (sci_read(SCI_STATUS) & 0xF0) >> 4;
christi_s 0:7728d9c6c487 337 if (i == 4) {
christi_s 2:5bab956cb59e 338
christi_s 2:5bab956cb59e 339 DEBUGOUT("VS1053b: Installed Chip is: VS1053\r\n");
christi_s 2:5bab956cb59e 340
christi_s 1:ced2c297cc1b 341 sci_write(SCI_CLOCKF, (SC_MULT_XTALIx50));
christi_s 1:ced2c297cc1b 342 wait_ms(10);
christi_s 0:7728d9c6c487 343 #ifdef VS_PATCH
christi_s 0:7728d9c6c487 344 // loading patch
christi_s 1:ced2c297cc1b 345 write_plugin(vs1053b_patch, sizeof(vs1053b_patch)/2);
christi_s 2:5bab956cb59e 346
christi_s 2:5bab956cb59e 347 DEBUGOUT("VS1053b: Patch is loaded.\r\n");
christi_s 2:5bab956cb59e 348 DEBUGOUT("VS1053b: Patch size:%d bytes\r\n",sizeof(vs1053b_patch));
christi_s 1:ced2c297cc1b 349
christi_s 1:ced2c297cc1b 350 #endif // VS_PATCH
christi_s 1:ced2c297cc1b 351 }
christi_s 1:ced2c297cc1b 352 else
christi_s 1:ced2c297cc1b 353 {
christi_s 2:5bab956cb59e 354 DEBUGOUT("VS1053b: Not Supported Chip\r\n");
christi_s 1:ced2c297cc1b 355 return false;
christi_s 1:ced2c297cc1b 356 }
christi_s 1:ced2c297cc1b 357
christi_s 1:ced2c297cc1b 358 // change spi to higher speed
christi_s 1:ced2c297cc1b 359 sdi_initialise();
christi_s 1:ced2c297cc1b 360 changeVolume();
christi_s 4:cacb5e663fa9 361 changeBass();
christi_s 4:cacb5e663fa9 362 _isIdle = true;
christi_s 1:ced2c297cc1b 363 return true;
christi_s 0:7728d9c6c487 364 }
christi_s 0:7728d9c6c487 365
christi_s 1:ced2c297cc1b 366 void VS1053::setVolume(float vol)
christi_s 1:ced2c297cc1b 367 {
christi_s 1:ced2c297cc1b 368 if (vol > -0.5)
christi_s 1:ced2c297cc1b 369 _volume = -0.5;
christi_s 1:ced2c297cc1b 370 else
christi_s 1:ced2c297cc1b 371 _volume = vol;
christi_s 1:ced2c297cc1b 372
christi_s 1:ced2c297cc1b 373 changeVolume();
christi_s 1:ced2c297cc1b 374 }
christi_s 1:ced2c297cc1b 375
christi_s 1:ced2c297cc1b 376 float VS1053::getVolume(void)
christi_s 1:ced2c297cc1b 377 {
christi_s 1:ced2c297cc1b 378 return _volume;
christi_s 0:7728d9c6c487 379 }
christi_s 1:ced2c297cc1b 380
christi_s 1:ced2c297cc1b 381 void VS1053::setBalance(float balance)
christi_s 1:ced2c297cc1b 382 {
christi_s 1:ced2c297cc1b 383 _balance = balance;
christi_s 1:ced2c297cc1b 384
christi_s 1:ced2c297cc1b 385 changeVolume();
christi_s 1:ced2c297cc1b 386 }
christi_s 1:ced2c297cc1b 387
christi_s 1:ced2c297cc1b 388 float VS1053::getBalance(void)
christi_s 1:ced2c297cc1b 389 {
christi_s 1:ced2c297cc1b 390 return _balance;
christi_s 1:ced2c297cc1b 391 }
christi_s 1:ced2c297cc1b 392
christi_s 1:ced2c297cc1b 393 void VS1053::changeVolume(void)
christi_s 1:ced2c297cc1b 394 {
christi_s 1:ced2c297cc1b 395 // volume calculation
christi_s 1:ced2c297cc1b 396 unsigned short volCalced = (((char)(_volume / -0.5f)) << 8) + (char)((_volume - _balance) / -0.5f);
christi_s 1:ced2c297cc1b 397
christi_s 2:5bab956cb59e 398 sci_write(SCI_VOL, volCalced);
christi_s 2:5bab956cb59e 399
christi_s 2:5bab956cb59e 400 DEBUGOUT("VS1053b: Change volume to %#x (%f, Balance = %f)\r\n", volCalced, _volume, _balance);
christi_s 2:5bab956cb59e 401 }
christi_s 2:5bab956cb59e 402
christi_s 2:5bab956cb59e 403 int VS1053::getTrebleFrequency(void)
christi_s 2:5bab956cb59e 404 {
christi_s 2:5bab956cb59e 405 return _st_freqlimit * 1000;
christi_s 2:5bab956cb59e 406 }
christi_s 2:5bab956cb59e 407
christi_s 2:5bab956cb59e 408
christi_s 2:5bab956cb59e 409 void VS1053::setTrebleFrequency(int frequency)
christi_s 2:5bab956cb59e 410 {
christi_s 2:5bab956cb59e 411 frequency /= 1000;
christi_s 2:5bab956cb59e 412
christi_s 2:5bab956cb59e 413 if(frequency < 1)
christi_s 2:5bab956cb59e 414 {
christi_s 2:5bab956cb59e 415 frequency = 1;
christi_s 2:5bab956cb59e 416 }
christi_s 2:5bab956cb59e 417 else if(frequency > 15)
christi_s 2:5bab956cb59e 418 {
christi_s 2:5bab956cb59e 419 frequency = 15;
christi_s 2:5bab956cb59e 420 }
christi_s 2:5bab956cb59e 421 _st_freqlimit = frequency;
christi_s 2:5bab956cb59e 422 changeBass();
christi_s 2:5bab956cb59e 423 }
christi_s 2:5bab956cb59e 424
christi_s 2:5bab956cb59e 425 int VS1053::getTrebleAmplitude(void)
christi_s 2:5bab956cb59e 426 {
christi_s 2:5bab956cb59e 427 return _st_amplitude;
christi_s 2:5bab956cb59e 428 }
christi_s 2:5bab956cb59e 429
christi_s 2:5bab956cb59e 430 void VS1053::setTrebleAmplitude(int amplitude)
christi_s 2:5bab956cb59e 431 {
christi_s 2:5bab956cb59e 432 if(amplitude < -8)
christi_s 2:5bab956cb59e 433 {
christi_s 2:5bab956cb59e 434 amplitude = -8;
christi_s 2:5bab956cb59e 435 }
christi_s 2:5bab956cb59e 436 else if(amplitude > 7)
christi_s 2:5bab956cb59e 437 {
christi_s 2:5bab956cb59e 438 amplitude = 7;
christi_s 2:5bab956cb59e 439 }
christi_s 2:5bab956cb59e 440 _st_amplitude = amplitude;
christi_s 2:5bab956cb59e 441 changeBass();
christi_s 2:5bab956cb59e 442 }
christi_s 1:ced2c297cc1b 443
christi_s 2:5bab956cb59e 444 int VS1053::getBassFrequency(void)
christi_s 2:5bab956cb59e 445 {
christi_s 2:5bab956cb59e 446 return _sb_freqlimit * 10;
christi_s 2:5bab956cb59e 447 }
christi_s 2:5bab956cb59e 448
christi_s 2:5bab956cb59e 449 void VS1053::setBassFrequency(int frequency)
christi_s 2:5bab956cb59e 450 {
christi_s 2:5bab956cb59e 451 frequency /= 10;
christi_s 2:5bab956cb59e 452
christi_s 2:5bab956cb59e 453 if(frequency < 2)
christi_s 2:5bab956cb59e 454 {
christi_s 2:5bab956cb59e 455 frequency = 2;
christi_s 2:5bab956cb59e 456 }
christi_s 2:5bab956cb59e 457 else if(frequency > 15)
christi_s 2:5bab956cb59e 458 {
christi_s 2:5bab956cb59e 459 frequency = 15;
christi_s 2:5bab956cb59e 460 }
christi_s 2:5bab956cb59e 461 _sb_freqlimit = frequency;
christi_s 2:5bab956cb59e 462 changeBass();
christi_s 2:5bab956cb59e 463 }
christi_s 2:5bab956cb59e 464
christi_s 2:5bab956cb59e 465 int VS1053::getBassAmplitude(void)
christi_s 2:5bab956cb59e 466 {
christi_s 2:5bab956cb59e 467 return _sb_amplitude;
christi_s 1:ced2c297cc1b 468 }
christi_s 2:5bab956cb59e 469
christi_s 2:5bab956cb59e 470 void VS1053::setBassAmplitude(int amplitude)
christi_s 2:5bab956cb59e 471 {
christi_s 2:5bab956cb59e 472 if(amplitude < -15)
christi_s 2:5bab956cb59e 473 {
christi_s 2:5bab956cb59e 474 amplitude = -15;
christi_s 2:5bab956cb59e 475 }
christi_s 2:5bab956cb59e 476 else if(amplitude > 0)
christi_s 2:5bab956cb59e 477 {
christi_s 2:5bab956cb59e 478 amplitude = 0;
christi_s 2:5bab956cb59e 479 }
christi_s 2:5bab956cb59e 480 _sb_amplitude = amplitude;
christi_s 2:5bab956cb59e 481 changeBass();
christi_s 2:5bab956cb59e 482 }
christi_s 2:5bab956cb59e 483
christi_s 2:5bab956cb59e 484 void VS1053::changeBass(void)
christi_s 2:5bab956cb59e 485 {
christi_s 2:5bab956cb59e 486 unsigned short bassCalced = ((_st_amplitude & 0x0f) << 12)
christi_s 2:5bab956cb59e 487 | ((_st_freqlimit & 0x0f) << 8)
christi_s 2:5bab956cb59e 488 | ((_sb_amplitude & 0x0f) << 4)
christi_s 2:5bab956cb59e 489 | ((_sb_freqlimit & 0x0f) << 0);
christi_s 2:5bab956cb59e 490
christi_s 2:5bab956cb59e 491 sci_write(SCI_BASS, bassCalced);
christi_s 2:5bab956cb59e 492
christi_s 2:5bab956cb59e 493 DEBUGOUT("VS1053b: Change bass settings to:\r\n")
christi_s 2:5bab956cb59e 494 DEBUGOUT("VS1053b: --Treble: Amplitude=%i, Frequency=%i\r\n", getTrebleAmplitude(), getTrebleFrequency());
christi_s 2:5bab956cb59e 495 DEBUGOUT("VS1053b: --Bass: Amplitude=%i, Frequency=%i\r\n", getBassAmplitude(), getBassFrequency());
christi_s 2:5bab956cb59e 496 }
christi_s 4:cacb5e663fa9 497
christi_s 4:cacb5e663fa9 498 /*===================================================================
christi_s 4:cacb5e663fa9 499 * Buffer handling
christi_s 4:cacb5e663fa9 500 *==================================================================*/
christi_s 4:cacb5e663fa9 501
christi_s 4:cacb5e663fa9 502 unsigned char VS1053::bufferGetByte(void)
christi_s 4:cacb5e663fa9 503 {
christi_s 4:cacb5e663fa9 504 unsigned char retVal = 0x00;
christi_s 4:cacb5e663fa9 505 if (bufferCount() > 0x00)
christi_s 4:cacb5e663fa9 506 {
christi_s 4:cacb5e663fa9 507 retVal = *_bufferReadPointer++;
christi_s 4:cacb5e663fa9 508 if (_bufferReadPointer >= _buffer + BUFFER_SIZE)
christi_s 4:cacb5e663fa9 509 {
christi_s 4:cacb5e663fa9 510 _bufferReadPointer = _buffer;
christi_s 4:cacb5e663fa9 511 }
christi_s 4:cacb5e663fa9 512 }
christi_s 4:cacb5e663fa9 513 return retVal;
christi_s 4:cacb5e663fa9 514 }
christi_s 4:cacb5e663fa9 515
christi_s 4:cacb5e663fa9 516 bool VS1053::bufferSetByte(unsigned char c)
christi_s 4:cacb5e663fa9 517 {
christi_s 4:cacb5e663fa9 518 if (bufferFree() > 0x00)
christi_s 4:cacb5e663fa9 519 {
christi_s 4:cacb5e663fa9 520 *_bufferWritePointer++ = c;
christi_s 4:cacb5e663fa9 521 if (_bufferWritePointer >= _buffer + BUFFER_SIZE)
christi_s 4:cacb5e663fa9 522 {
christi_s 4:cacb5e663fa9 523 _bufferWritePointer = _buffer;
christi_s 4:cacb5e663fa9 524 }
christi_s 4:cacb5e663fa9 525 return true;
christi_s 4:cacb5e663fa9 526 }
christi_s 4:cacb5e663fa9 527 return false;
christi_s 4:cacb5e663fa9 528 }
christi_s 4:cacb5e663fa9 529
christi_s 4:cacb5e663fa9 530 bool VS1053::bufferPutStream(const unsigned char *s, unsigned int length)
christi_s 4:cacb5e663fa9 531 {
christi_s 4:cacb5e663fa9 532 if (bufferFree() >= length)
christi_s 4:cacb5e663fa9 533 {
christi_s 4:cacb5e663fa9 534 while (length--)
christi_s 4:cacb5e663fa9 535 {
christi_s 4:cacb5e663fa9 536 *_bufferWritePointer++ = *s++;
christi_s 4:cacb5e663fa9 537 if (_bufferWritePointer >= _buffer + BUFFER_SIZE)
christi_s 4:cacb5e663fa9 538 {
christi_s 4:cacb5e663fa9 539 _bufferWritePointer = _buffer;
christi_s 4:cacb5e663fa9 540 }
christi_s 4:cacb5e663fa9 541 }
christi_s 4:cacb5e663fa9 542 return true;
christi_s 4:cacb5e663fa9 543 }
christi_s 4:cacb5e663fa9 544 return false;
christi_s 4:cacb5e663fa9 545 }
christi_s 4:cacb5e663fa9 546
christi_s 4:cacb5e663fa9 547 unsigned int VS1053::bufferFree(void)
christi_s 4:cacb5e663fa9 548 {
christi_s 4:cacb5e663fa9 549 if(_bufferReadPointer > _bufferWritePointer)
christi_s 4:cacb5e663fa9 550 {
christi_s 4:cacb5e663fa9 551 return _bufferReadPointer - _bufferWritePointer - 1;
christi_s 4:cacb5e663fa9 552 }
christi_s 4:cacb5e663fa9 553 else if(_bufferReadPointer < _bufferWritePointer)
christi_s 4:cacb5e663fa9 554 {
christi_s 4:cacb5e663fa9 555 return BUFFER_SIZE - (_bufferWritePointer - _bufferReadPointer) - 1;
christi_s 4:cacb5e663fa9 556 }
christi_s 4:cacb5e663fa9 557 return BUFFER_SIZE - 1;
christi_s 4:cacb5e663fa9 558 }
christi_s 4:cacb5e663fa9 559
christi_s 4:cacb5e663fa9 560 unsigned int VS1053::bufferCount(void)
christi_s 4:cacb5e663fa9 561 {
christi_s 4:cacb5e663fa9 562 return BUFFER_SIZE - bufferFree() - 1;
christi_s 4:cacb5e663fa9 563 }
christi_s 4:cacb5e663fa9 564
christi_s 4:cacb5e663fa9 565 void VS1053::bufferReset(void)
christi_s 4:cacb5e663fa9 566 {
christi_s 4:cacb5e663fa9 567 _bufferReadPointer = _buffer;
christi_s 4:cacb5e663fa9 568 _bufferWritePointer = _buffer;
christi_s 4:cacb5e663fa9 569 }
christi_s 4:cacb5e663fa9 570
christi_s 4:cacb5e663fa9 571
christi_s 4:cacb5e663fa9 572 void VS1053::dataRequestHandler(void)
christi_s 4:cacb5e663fa9 573 {
christi_s 4:cacb5e663fa9 574 if (_isIdle && _DREQ)
christi_s 4:cacb5e663fa9 575 {
christi_s 4:cacb5e663fa9 576 _isIdle = false;
christi_s 4:cacb5e663fa9 577 // write buffer to vs1053b
christi_s 4:cacb5e663fa9 578 unsigned length = bufferCount();
christi_s 4:cacb5e663fa9 579 int i = 0;
christi_s 4:cacb5e663fa9 580 sdi_en();
christi_s 4:cacb5e663fa9 581
christi_s 4:cacb5e663fa9 582 while (length > 0)
christi_s 4:cacb5e663fa9 583 {
christi_s 4:cacb5e663fa9 584 int l2 = (length > 32) ? 32 : length;
christi_s 4:cacb5e663fa9 585 //DEBUGOUT("L2: %i\r\n", l2);
christi_s 4:cacb5e663fa9 586 for( ; l2 != 0; l2--)
christi_s 4:cacb5e663fa9 587 {
christi_s 4:cacb5e663fa9 588 _spi.write(bufferGetByte());
christi_s 4:cacb5e663fa9 589 }
christi_s 4:cacb5e663fa9 590
christi_s 4:cacb5e663fa9 591 length -= l2;
christi_s 4:cacb5e663fa9 592
christi_s 4:cacb5e663fa9 593 if (!_DREQ || i > 4)
christi_s 4:cacb5e663fa9 594 break;
christi_s 4:cacb5e663fa9 595 i++;
christi_s 4:cacb5e663fa9 596 }
christi_s 4:cacb5e663fa9 597
christi_s 4:cacb5e663fa9 598 sdi_dis();
christi_s 4:cacb5e663fa9 599
christi_s 4:cacb5e663fa9 600 _isIdle = true;
christi_s 4:cacb5e663fa9 601 }
christi_s 4:cacb5e663fa9 602 }
christi_s 4:cacb5e663fa9 603
christi_s 4:cacb5e663fa9 604 void VS1053::play(void)
christi_s 4:cacb5e663fa9 605 {
christi_s 4:cacb5e663fa9 606 INTERRUPT_HANDLER_ENABLE;
christi_s 4:cacb5e663fa9 607 DEBUGOUT("VS1053b: Play.\r\n");
christi_s 4:cacb5e663fa9 608 }
christi_s 4:cacb5e663fa9 609
christi_s 4:cacb5e663fa9 610 void VS1053::pause(void)
christi_s 4:cacb5e663fa9 611 {
christi_s 4:cacb5e663fa9 612 INTERRUPT_HANDLER_DISABLE;
christi_s 4:cacb5e663fa9 613 DEBUGOUT("VS1053b: Pause.\r\n");
christi_s 4:cacb5e663fa9 614 }
christi_s 4:cacb5e663fa9 615
christi_s 4:cacb5e663fa9 616 void VS1053::stop(void)
christi_s 4:cacb5e663fa9 617 {
christi_s 4:cacb5e663fa9 618 INTERRUPT_HANDLER_DISABLE;
christi_s 4:cacb5e663fa9 619 __disable_irq();
christi_s 4:cacb5e663fa9 620 DEBUGOUT("VS1053b: Song stoping..\r\n");
christi_s 4:cacb5e663fa9 621 while(!_isIdle)
christi_s 4:cacb5e663fa9 622 ;
christi_s 4:cacb5e663fa9 623
christi_s 4:cacb5e663fa9 624 // set SCI MODE bit SM CANCEL
christi_s 4:cacb5e663fa9 625 unsigned short sciModeByte = sci_read(SCI_MODE);
christi_s 4:cacb5e663fa9 626 sciModeByte |= SM_CANCEL;
christi_s 4:cacb5e663fa9 627 sci_write(SCI_MODE, sciModeByte);
christi_s 4:cacb5e663fa9 628
christi_s 4:cacb5e663fa9 629 // send up 2048 bytes of audio data.
christi_s 4:cacb5e663fa9 630 for (int i = 0; i < 64; i++)
christi_s 4:cacb5e663fa9 631 {
christi_s 4:cacb5e663fa9 632 // send at least 32 bytes of audio data
christi_s 4:cacb5e663fa9 633 int z = bufferCount();
christi_s 4:cacb5e663fa9 634 if (z > 32)
christi_s 4:cacb5e663fa9 635 z = 32;
christi_s 4:cacb5e663fa9 636 for (int n = 0; n < z; n++)
christi_s 4:cacb5e663fa9 637 {
christi_s 4:cacb5e663fa9 638 _spi.write(bufferGetByte());
christi_s 4:cacb5e663fa9 639 }
christi_s 4:cacb5e663fa9 640 // read SCI MODE; if SM CANCEL is still set, repeat
christi_s 4:cacb5e663fa9 641 sciModeByte = sci_read(SCI_MODE);
christi_s 4:cacb5e663fa9 642 if ((sciModeByte & SM_CANCEL) == 0x0000)
christi_s 4:cacb5e663fa9 643 {
christi_s 4:cacb5e663fa9 644 break;
christi_s 4:cacb5e663fa9 645 }
christi_s 4:cacb5e663fa9 646 }
christi_s 4:cacb5e663fa9 647
christi_s 4:cacb5e663fa9 648 if ((sciModeByte & SM_CANCEL) == 0x0000)
christi_s 4:cacb5e663fa9 649 {
christi_s 4:cacb5e663fa9 650 // send at least 2052 bytes of endFillByte[7:0].
christi_s 4:cacb5e663fa9 651 // read endFillByte (0 .. 15) from wram
christi_s 4:cacb5e663fa9 652 unsigned short endFillByte=wram_read(para_endFillByte);
christi_s 4:cacb5e663fa9 653 // clear endFillByte (8 .. 15)
christi_s 4:cacb5e663fa9 654 endFillByte = endFillByte ^0x00FF;
christi_s 4:cacb5e663fa9 655 for (int n = 0; n < 2052; n++)
christi_s 4:cacb5e663fa9 656 sdi_write(endFillByte);
christi_s 4:cacb5e663fa9 657 DEBUGOUT("VS1053b: Song sucessfully stopped.\r\n");
christi_s 4:cacb5e663fa9 658 DEBUGOUT("VS1053b: SCI MODE = %#x, SM_CANCEL = %#x\r\n", sciModeByte, sciModeByte & SM_CANCEL);
christi_s 4:cacb5e663fa9 659 }
christi_s 4:cacb5e663fa9 660 else
christi_s 4:cacb5e663fa9 661 {
christi_s 4:cacb5e663fa9 662 DEBUGOUT("VS1053b: SM CANCEL hasn't cleared after sending 2048 bytes, do software reset\r\n");
christi_s 4:cacb5e663fa9 663 DEBUGOUT("VS1053b: SCI MODE = %#x, SM_CANCEL = %#x\r\n", sciModeByte, sciModeByte & SM_CANCEL);
christi_s 4:cacb5e663fa9 664 //TODO: testing
christi_s 4:cacb5e663fa9 665 initialize();
christi_s 4:cacb5e663fa9 666 }
christi_s 4:cacb5e663fa9 667
christi_s 4:cacb5e663fa9 668 bufferReset();
christi_s 4:cacb5e663fa9 669 __enable_irq();
christi_s 4:cacb5e663fa9 670 }