Add the RTOS processing. for the Network radio streaming receiver.
Fork of VS1053b by
VS1053.cpp
- Committer:
- christi_s
- Date:
- 2010-12-22
- Revision:
- 2:5bab956cb59e
- Parent:
- 1:ced2c297cc1b
- Child:
- 3:88a645490529
File content as of revision 2:5bab956cb59e:
/* mbed VLSI VS1053b library * Copyright (c) 2010 Christian Schmiljun * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ /* This code based on: * mbeduino_MP3_Shield_MP3Player * http://mbed.org/users/xshige/programs/mbeduino_MP3_Shield_MP3Player/lgcx63 * 2010-10-16 */ #include "VS1053.h" #include "mbed.h" // patch binarys #include "Patches/VS1053b_patch_1_5.c" #include "Patches/VS1053b_patch_1_5_flac.c" #include "Patches/VS1053b_patch_1_4_flac.c" #include "Patches/VS1053b_specana_0_9.c" #include "Patches/VS1053b_pcm_recorder_0_9.c" /* ================================================================== * Constructor * =================================================================*/ VS1053::VS1053( PinName mosi, PinName miso, PinName sck, PinName cs, PinName rst, PinName dreq, PinName dcs) : _spi(mosi, miso, sck), _CS(cs), _RST(rst), _DREQ(dreq), _DCS(dcs) { _volume = DEFAULT_VOLUME; _balance = DEFAULT_BALANCE_DIFERENCE_LEFT_RIGHT; _sb_amplitude = DEFAULT_BASS_AMPLITUDE; _sb_freqlimit = DEFAULT_BASS_FREQUENCY; _st_amplitude = DEFAULT_TREBLE_AMPLITUDE; _st_freqlimit = DEFAULT_TREBLE_FREQUENCY; } /*=================================================================== * Functions *==================================================================*/ void VS1053::cs_low(void) { _CS = 0; } void VS1053::cs_high(void) { _CS = 1; } void VS1053::dcs_low(void) { _DCS = 0; } void VS1053::dcs_high(void) { _DCS = 1; } void VS1053::sci_en(void) { //SCI enable cs_high(); dcs_high(); cs_low(); } void VS1053::sci_dis(void) { //SCI disable cs_high(); } void VS1053::sdi_en(void) { //SDI enable dcs_high(); cs_high(); dcs_low(); } void VS1053::sdi_dis(void) { //SDI disable dcs_high(); } void VS1053::reset(void) { //hardware reset // wait(0.01); wait_ms(10); _RST = 0; // wait(0.01); wait_ms(5); _RST = 1; // wait(0.10); wait_ms(10); } void VS1053::power_down(void) { //hardware and software reset cs_low(); reset(); // sci_write(0x00, SM_PDOWN); sci_write(0x00, 0x10); // tempo wait(0.01); reset(); } void VS1053::spi_initialise(void) { _RST = 1; //no reset _spi.format(8,0); //spi 8bit interface, steady state low // _spi.frequency(1000000); //rising edge data record, freq. 1Mhz _spi.frequency(2000000); //rising edge data record, freq. 2Mhz cs_low(); for (int i=0; i<4; i++) { _spi.write(0xFF); //clock the chip a bit } cs_high(); dcs_high(); wait_us(5); } void VS1053::sdi_initialise(void) { _spi.frequency(8000000); //set to 8 MHz to make fast transfer cs_high(); dcs_high(); } void VS1053::sci_write(unsigned char address, unsigned short int data) { sci_en(); //enables SCI/disables SDI while (!_DREQ); //wait unitl data request is high _spi.write(0x02); //SCI write _spi.write(address); //register address _spi.write((data >> 8) & 0xFF); //write out first half of data word _spi.write(data & 0xFF); //write out second half of data word sci_dis(); //enables SDI/disables SCI wait_us(5); } void VS1053::sdi_write(unsigned char datum) { sdi_en(); while (!_DREQ); _spi.write(datum); //? sci_dis(); sdi_dis(); } unsigned short VS1053::sci_read(unsigned short int address) { cs_low(); //enables SCI/disables SDI while (!_DREQ); //wait unitl data request is high _spi.write(0x03); //SCI write _spi.write(address); //register address unsigned short int received = _spi.write(0x00); //write out dummy byte received <<= 8; received += _spi.write(0x00); //write out dummy byte cs_high(); //enables SDI/disables SCI return received; //return received word } void VS1053::sine_test_activate(unsigned char wave) { cs_high(); //enables SDI/disables SCI while (!_DREQ); //wait unitl data request is high _spi.write(0x53); //SDI write _spi.write(0xEF); //SDI write _spi.write(0x6E); //SDI write _spi.write(wave); //SDI write _spi.write(0x00); //filler byte _spi.write(0x00); //filler byte _spi.write(0x00); //filler byte _spi.write(0x00); //filler byte cs_low(); //enables SCI/disables SDI } void VS1053::sine_test_deactivate(void) { cs_high(); while (!_DREQ); _spi.write(0x45); //SDI write _spi.write(0x78); //SDI write _spi.write(0x69); //SDI write _spi.write(0x74); //SDI write _spi.write(0x00); //filler byte _spi.write(0x00); //filler byte _spi.write(0x00); //filler byte _spi.write(0x00); //filler byte } void VS1053::writeStream(unsigned char *array, unsigned int size) { for (int i=0; i<size; i++) { sdi_write(array[i]); } } #if 0 // this function does not work // because of function call overhead void VS1053::putcStream(unsigned char datum) { sdi_write(datum); } #endif unsigned short int VS1053::wram_read(unsigned short int address) { unsigned short int tmp1,tmp2; sci_write(SCI_WRAMADDR,address); tmp1=sci_read(SCI_WRAM); sci_write(SCI_WRAMADDR,address); tmp2=sci_read(SCI_WRAM); if (tmp1==tmp2) return tmp1; sci_write(SCI_WRAMADDR,address); tmp1=sci_read(SCI_WRAM); if (tmp1==tmp2) return tmp1; sci_write(SCI_WRAMADDR,address); tmp1=sci_read(SCI_WRAM); if (tmp1==tmp2) return tmp1; return tmp1; } void VS1053::wram_write(unsigned short int address, unsigned short int data) { sci_write(SCI_WRAMADDR,address); sci_write(SCI_WRAM,data); return; } void VS1053::setPlaySpeed(unsigned short speed) { wram_write(para_playSpeed, speed); DEBUGOUT("VS1053b: Change speed. New speed: %d\r\n", speed); } void VS1053::terminateStream(void) { // send at least 2052 bytes of endFillByte[7:0]. // read endFillByte (0 .. 15) from wram unsigned short endFillByte=wram_read(para_endFillByte); // clear endFillByte (8 .. 15) endFillByte = endFillByte ^0x00FF; for (int n = 0; n < 2052; n++) sdi_write(endFillByte); // set SCI MODE bit SM CANCEL unsigned short sciModeByte = sci_read(SCI_MODE); sciModeByte |= SM_CANCEL; sci_write(SCI_MODE, sciModeByte); // send up 2048 bytes of endFillByte[7:0]. for (int i = 0; i < 64; i++) { // send at least 32 bytes of endFillByte[7:0] for (int n = 0; n < 32; n++) sdi_write(endFillByte); // read SCI MODE; if SM CANCEL is still set, repeat sciModeByte = sci_read(SCI_MODE); if ((sciModeByte & SM_CANCEL) == 0x0000) { break; } } if ((sciModeByte & SM_CANCEL) == 0x0000) { DEBUGOUT("VS1053b: Song sucessfully sent. Terminating OK\r\n"); DEBUGOUT("VS1053b: SCI MODE = %#x, SM_CANCEL = %#x\r\n", sciModeByte, sciModeByte & SM_CANCEL); } else { DEBUGOUT("VS1053b: SM CANCEL hasn't cleared after sending 2048 bytes, do software reset\r\n"); DEBUGOUT("VS1053b: SCI MODE = %#x, SM_CANCEL = %#x\r\n", sciModeByte, sciModeByte & SM_CANCEL); //TODO: testing initialize(); } } void VS1053::write_plugin(const unsigned short *plugin, unsigned int len) { unsigned int i; unsigned short addr, n, val; for (i=0; i<len;) { addr = plugin[i++]; n = plugin[i++]; if (n & 0x8000U) { //RLE run, replicate n samples n &= 0x7FFF; val = plugin[i++]; while (n--) { sci_write(addr,val); } } else { //copy run, copy n sample while (n--) { val = plugin[i++]; sci_write(addr,val); } } } return; } bool VS1053::initialize(void) { _RST = 1; cs_high(); //chip disabled spi_initialise(); //initialise MBED sci_write(SCI_MODE, (SM_SDINEW+SM_RESET)); // set mode reg. wait_ms(10); #ifdef DEBUG unsigned int info = wram_read(para_chipID_0); DEBUGOUT("VS1053b: ChipID_0:%04X\r\n", info); info = wram_read(para_chipID_1); DEBUGOUT("VS1053b: ChipID_1:%04X\r\n", info); info = wram_read(para_version); DEBUGOUT("VS1053b: Structure version:%04X\r\n", info); #endif //get chip version, set clock multiplier and load patch int i = (sci_read(SCI_STATUS) & 0xF0) >> 4; if (i == 4) { DEBUGOUT("VS1053b: Installed Chip is: VS1053\r\n"); sci_write(SCI_CLOCKF, (SC_MULT_XTALIx50)); wait_ms(10); #ifdef VS_PATCH // loading patch write_plugin(vs1053b_patch, sizeof(vs1053b_patch)/2); DEBUGOUT("VS1053b: Patch is loaded.\r\n"); DEBUGOUT("VS1053b: Patch size:%d bytes\r\n",sizeof(vs1053b_patch)); #endif // VS_PATCH } else { DEBUGOUT("VS1053b: Not Supported Chip\r\n"); return false; } // change spi to higher speed sdi_initialise(); changeVolume(); return true; } void VS1053::setVolume(float vol) { if (vol > -0.5) _volume = -0.5; else _volume = vol; changeVolume(); } float VS1053::getVolume(void) { return _volume; } void VS1053::setBalance(float balance) { _balance = balance; changeVolume(); } float VS1053::getBalance(void) { return _balance; } void VS1053::changeVolume(void) { // volume calculation unsigned short volCalced = (((char)(_volume / -0.5f)) << 8) + (char)((_volume - _balance) / -0.5f); sci_write(SCI_VOL, volCalced); DEBUGOUT("VS1053b: Change volume to %#x (%f, Balance = %f)\r\n", volCalced, _volume, _balance); } int VS1053::getTrebleFrequency(void) { return _st_freqlimit * 1000; } void VS1053::setTrebleFrequency(int frequency) { frequency /= 1000; if(frequency < 1) { frequency = 1; } else if(frequency > 15) { frequency = 15; } _st_freqlimit = frequency; changeBass(); } int VS1053::getTrebleAmplitude(void) { return _st_amplitude; } void VS1053::setTrebleAmplitude(int amplitude) { if(amplitude < -8) { amplitude = -8; } else if(amplitude > 7) { amplitude = 7; } _st_amplitude = amplitude; changeBass(); } int VS1053::getBassFrequency(void) { return _sb_freqlimit * 10; } void VS1053::setBassFrequency(int frequency) { frequency /= 10; if(frequency < 2) { frequency = 2; } else if(frequency > 15) { frequency = 15; } _sb_freqlimit = frequency; changeBass(); } int VS1053::getBassAmplitude(void) { return _sb_amplitude; } void VS1053::setBassAmplitude(int amplitude) { if(amplitude < -15) { amplitude = -15; } else if(amplitude > 0) { amplitude = 0; } _sb_amplitude = amplitude; changeBass(); } void VS1053::changeBass(void) { unsigned short bassCalced = ((_st_amplitude & 0x0f) << 12) | ((_st_freqlimit & 0x0f) << 8) | ((_sb_amplitude & 0x0f) << 4) | ((_sb_freqlimit & 0x0f) << 0); sci_write(SCI_BASS, bassCalced); DEBUGOUT("VS1053b: Change bass settings to:\r\n") DEBUGOUT("VS1053b: --Treble: Amplitude=%i, Frequency=%i\r\n", getTrebleAmplitude(), getTrebleFrequency()); DEBUGOUT("VS1053b: --Bass: Amplitude=%i, Frequency=%i\r\n", getBassAmplitude(), getBassFrequency()); }