From 279790722158ed0b4769b2dc7781c42d77104e9c Mon Sep 17 00:00:00 2001 From: Roger Clark Date: Sat, 6 Jun 2015 07:46:42 +1000 Subject: [PATCH] Added support for SPI 2 to VS1003 library, and made a change to SPI to support other libs being able to select which SPI they want to use (issue with const in transfer() --- STM32F1/libraries/SPI/src/SPI.cpp | 2 +- STM32F1/libraries/SPI/src/SPI.h | 2 +- .../Serasidis_VS1003B_STM/VS1003_STM.cpp | 124 +++++++++--------- .../Serasidis_VS1003B_STM/VS1003_STM.h | 16 +-- .../examples/hello_STM/hello_STM.ino | 37 +++--- 5 files changed, 88 insertions(+), 93 deletions(-) diff --git a/STM32F1/libraries/SPI/src/SPI.cpp b/STM32F1/libraries/SPI/src/SPI.cpp index da936fa..f17d804 100644 --- a/STM32F1/libraries/SPI/src/SPI.cpp +++ b/STM32F1/libraries/SPI/src/SPI.cpp @@ -347,7 +347,7 @@ void SPIClass::write(const uint8 *data, uint32 length) { while (spi_is_busy(this->spi_d) != 0); // "... then wait until BSY=0, this indicates that the transmission of the last data is complete." } -uint8 SPIClass::transfer(uint8 byte) { +uint8 SPIClass::transfer(uint8 byte) const { uint8 b; spi_tx_reg(this->spi_d, byte); // "2. Write the first data item to be transmitted into the SPI_DR register (this clears the TXE flag)." while (spi_is_rx_nonempty(this->spi_d) == 0); // "4. Wait until RXNE=1 ..." diff --git a/STM32F1/libraries/SPI/src/SPI.h b/STM32F1/libraries/SPI/src/SPI.h index 4ec2723..490d58b 100644 --- a/STM32F1/libraries/SPI/src/SPI.h +++ b/STM32F1/libraries/SPI/src/SPI.h @@ -238,7 +238,7 @@ public: * @param data Byte to transmit. * @return Next unread byte. */ - uint8 transfer(uint8 data); + uint8 transfer(uint8 data) const; /** * @brief Sets up a DMA Transfer for "length" bytes. diff --git a/STM32F1/libraries/Serasidis_VS1003B_STM/VS1003_STM.cpp b/STM32F1/libraries/Serasidis_VS1003B_STM/VS1003_STM.cpp index 1063049..2f80b19 100644 --- a/STM32F1/libraries/Serasidis_VS1003B_STM/VS1003_STM.cpp +++ b/STM32F1/libraries/Serasidis_VS1003B_STM/VS1003_STM.cpp @@ -12,16 +12,10 @@ mp3 decoding instead of booting into MID (modeSwitch function). */ -#include +//#include #include -const uint8_t vs1003_chunk_size = 32; - -#undef PROGMEM -#define PROGMEM __attribute__ ((section (".progmem.data"))) -#undef PSTR -#define PSTR(s) (__extension__({static char __c[] PROGMEM = (s); &__c[0];})) - +#define vs1003_chunk_size 32 /****************************************************************************/ // VS1003 SCI Write Command byte is 0x02 @@ -70,24 +64,24 @@ const uint8_t SM_LINE_IN = 14; // Register names -char reg_name_MODE[] PROGMEM = "MODE"; -char reg_name_STATUS[] PROGMEM = "STATUS"; -char reg_name_BASS[] PROGMEM = "BASS"; -char reg_name_CLOCKF[] PROGMEM = "CLOCKF"; -char reg_name_DECODE_TIME[] PROGMEM = "DECODE_TIME"; -char reg_name_AUDATA[] PROGMEM = "AUDATA"; -char reg_name_WRAM[] PROGMEM = "WRAM"; -char reg_name_WRAMADDR[] PROGMEM = "WRAMADDR"; -char reg_name_HDAT0[] PROGMEM = "HDAT0"; -char reg_name_HDAT1[] PROGMEM = "HDAT1"; -char reg_name_AIADDR[] PROGMEM = "AIADDR"; -char reg_name_VOL[] PROGMEM = "VOL"; -char reg_name_AICTRL0[] PROGMEM = "AICTRL0"; -char reg_name_AICTRL1[] PROGMEM = "AICTRL1"; -char reg_name_AICTRL2[] PROGMEM = "AICTRL2"; -char reg_name_AICTRL3[] PROGMEM = "AICTRL3"; +const char reg_name_MODE[] = "MODE"; +const char reg_name_STATUS[] = "STATUS"; +const char reg_name_BASS[] = "BASS"; +const char reg_name_CLOCKF[] = "CLOCKF"; +const char reg_name_DECODE_TIME[] = "DECODE_TIME"; +const char reg_name_AUDATA[] = "AUDATA"; +const char reg_name_WRAM[] = "WRAM"; +const char reg_name_WRAMADDR[] = "WRAMADDR"; +const char reg_name_HDAT0[] = "HDAT0"; +const char reg_name_HDAT1[] = "HDAT1"; +const char reg_name_AIADDR[] = "AIADDR"; +const char reg_name_VOL[] = "VOL"; +const char reg_name_AICTRL0[] = "AICTRL0"; +const char reg_name_AICTRL1[] = "AICTRL1"; +const char reg_name_AICTRL2[] = "AICTRL2"; +const char reg_name_AICTRL3[] = "AICTRL3"; -static PGM_P register_names[] PROGMEM = +static PGM_P const register_names[] = { reg_name_MODE, reg_name_STATUS, @@ -116,15 +110,15 @@ inline void DMA1_CH3_Event() { /****************************************************************************/ -uint16_t VS1003_STM::read_register(uint8_t _reg) const +uint16_t VS1003::read_register(uint8_t _reg) const { uint16_t result; control_mode_on(); delayMicroseconds(1); // tXCSS - SPI.transfer(VS_READ_COMMAND); // Read operation - SPI.transfer(_reg); // Which register - result = SPI.transfer(0xff) << 8; // read high byte - result |= SPI.transfer(0xff); // read low byte + my_SPI.transfer(VS_READ_COMMAND); // Read operation + my_SPI.transfer(_reg); // Which register + result = my_SPI.transfer(0xff) << 8; // read high byte + result |= my_SPI.transfer(0xff); // read low byte delayMicroseconds(1); // tXCSH await_data_request(); control_mode_off(); @@ -133,14 +127,14 @@ uint16_t VS1003_STM::read_register(uint8_t _reg) const /****************************************************************************/ -void VS1003_STM::write_register(uint8_t _reg,uint16_t _value) const +void VS1003::write_register(uint8_t _reg,uint16_t _value) const { control_mode_on(); delayMicroseconds(1); // tXCSS - SPI.transfer(VS_WRITE_COMMAND); // Write operation - SPI.transfer(_reg); // Which register - SPI.transfer(_value >> 8); // Send hi byte - SPI.transfer(_value & 0xff); // Send lo byte + my_SPI.transfer(VS_WRITE_COMMAND); // Write operation + my_SPI.transfer(_reg); // Which register + my_SPI.transfer(_value >> 8); // Send hi byte + my_SPI.transfer(_value & 0xff); // Send lo byte delayMicroseconds(1); // tXCSH await_data_request(); control_mode_off(); @@ -148,7 +142,7 @@ void VS1003_STM::write_register(uint8_t _reg,uint16_t _value) const /****************************************************************************/ -void VS1003_STM::sdi_send_buffer(const uint8_t* data, size_t len) +void VS1003::sdi_send_buffer(const uint8_t* data, size_t len) { data_mode_on(); while ( len ) @@ -159,14 +153,14 @@ void VS1003_STM::sdi_send_buffer(const uint8_t* data, size_t len) size_t chunk_length = min(len,vs1003_chunk_size); len -= chunk_length; while ( chunk_length-- ) - SPI.transfer(*data++); + my_SPI.transfer(*data++); } data_mode_off(); } /****************************************************************************/ -void VS1003_STM::sdi_send_zeroes(size_t len) +void VS1003::sdi_send_zeroes(size_t len) { data_mode_on(); while ( len ) @@ -176,21 +170,21 @@ void VS1003_STM::sdi_send_zeroes(size_t len) size_t chunk_length = min(len,vs1003_chunk_size); len -= chunk_length; while ( chunk_length-- ) - SPI.transfer(0); + my_SPI.transfer(0); } data_mode_off(); } /****************************************************************************/ -VS1003_STM::VS1003_STM( uint8_t _cs_pin, uint8_t _dcs_pin, uint8_t _dreq_pin, uint8_t _reset_pin): - cs_pin(_cs_pin), dcs_pin(_dcs_pin), dreq_pin(_dreq_pin), reset_pin(_reset_pin) +VS1003::VS1003( uint8_t _cs_pin, uint8_t _dcs_pin, uint8_t _dreq_pin, uint8_t _reset_pin, SPIClass _spiChan): + cs_pin(_cs_pin), dcs_pin(_dcs_pin), dreq_pin(_dreq_pin), reset_pin(_reset_pin), my_SPI(_spiChan) { } /****************************************************************************/ -void VS1003_STM::begin(void) +void VS1003::begin(void) { // Keep the chip in reset until we are ready @@ -206,17 +200,19 @@ void VS1003_STM::begin(void) // DREQ is an input pinMode(dreq_pin,INPUT); + // Boot VS1003 - //Serial.println(PSTR("Booting VS1003...\r\n")); + //printf(("Booting VS1003...\r\n")); delay(1); - SPI.begin(); - SPI.setBitOrder(MSBFIRST); - SPI.setDataMode(SPI_MODE0); + my_SPI.begin(); + my_SPI.setBitOrder(MSBFIRST); + my_SPI.setDataMode(SPI_MODE0); // init SPI slow mode - SPI.setClockDivider(SPI_CLOCK_DIV64); // Slow! - + + my_SPI.setClockDivider(SPI_CLOCK_DIV64); // Slow! + // release from reset digitalWrite(reset_pin,HIGH); @@ -231,7 +227,7 @@ void VS1003_STM::begin(void) /* Switch on the analog parts */ write_register(SCI_VOL,0xfefe); // VOL - //printf_P(PSTR("VS1003 still booting\r\n")); + //printf(("VS1003 still booting\r\n")); write_register(SCI_AUDATA,44101); // 44.1kHz stereo @@ -248,17 +244,17 @@ void VS1003_STM::begin(void) // Now you can set high speed SPI clock // 72 MHz / 16 = 4.5 MHz max is practically allowed by VS1003 SPI interface. - SPI.setClockDivider(SPI_CLOCK_DIV16); + my_SPI.setClockDivider(SPI_CLOCK_DIV16); - //printf_P(PSTR("VS1003 Set\r\n")); + //printf(("VS1003 Set\r\n")); //printDetails(); - //printf_P(PSTR("VS1003 OK\r\n")); + //printf(("VS1003 OK\r\n")); } /****************************************************************************/ -void VS1003_STM::setVolume(uint8_t vol) const +void VS1003::setVolume(uint8_t vol) const { uint16_t value = vol; value <<= 8; @@ -269,46 +265,46 @@ void VS1003_STM::setVolume(uint8_t vol) const /****************************************************************************/ -void VS1003_STM::startSong(void) +void VS1003::startSong(void) { sdi_send_zeroes(10); } /****************************************************************************/ -void VS1003_STM::playChunk(const uint8_t* data, size_t len) +void VS1003::playChunk(const uint8_t* data, size_t len) { sdi_send_buffer(data,len); } /****************************************************************************/ -void VS1003_STM::stopSong(void) +void VS1003::stopSong(void) { sdi_send_zeroes(2048); } /****************************************************************************/ -void VS1003_STM::print_byte_register(uint8_t reg) const +void VS1003::print_byte_register(uint8_t reg) const { const char *name = reinterpret_cast(pgm_read_word( register_names + reg )); char extra_tab = strlen_P(name) < 5 ? '\t' : 0; - //printf_P(PSTR("%02x %S\t%c = 0x%02x\r\n"),reg,name,extra_tab,read_register(reg)); + //printf(("%02x %S\t%c = 0x%02x\r\n"),reg,name,extra_tab,read_register(reg)); } /****************************************************************************/ -void VS1003_STM::printDetails(void) const +void VS1003::printDetails(void) const { - //printf_P(PSTR("VS1003 Configuration:\r\n")); + //printf(("VS1003 Configuration:\r\n")); int i = 0; while ( i <= SCI_num_registers ) print_byte_register(i++); } /****************************************************************************/ -void VS1003_STM::modeSwitch(void) +void VS1003::modeSwitch(void) { //GPIO_DDR write_register(SCI_WRAMADDR, 0xc017); @@ -323,7 +319,7 @@ void VS1003_STM::modeSwitch(void) } /****************************************************************************/ -void VS1003_STM::loadUserCode(const uint16_t* buf, size_t len) const +void VS1003::loadUserCode(const uint16_t* buf, size_t len) const { while (len) { @@ -333,13 +329,13 @@ void VS1003_STM::loadUserCode(const uint16_t* buf, size_t len) const n &= 0x7FFF; uint16_t val = pgm_read_word(buf++); len--; while (n--) { - //printf_P(PSTR("W %02x: %04x\r\n"),addr,val); + //printf(("W %02x: %04x\r\n"),addr,val); write_register(addr, val); } } else { /* Copy run, copy n samples */ while (n--) { uint16_t val = pgm_read_word(buf++); len--; - //printf_P(PSTR("W %02x: %04x\r\n"),addr,val); + //printf(("W %02x: %04x\r\n"),addr,val); write_register(addr, val); } } diff --git a/STM32F1/libraries/Serasidis_VS1003B_STM/VS1003_STM.h b/STM32F1/libraries/Serasidis_VS1003B_STM/VS1003_STM.h index e1492e0..e9c7359 100644 --- a/STM32F1/libraries/Serasidis_VS1003B_STM/VS1003_STM.h +++ b/STM32F1/libraries/Serasidis_VS1003B_STM/VS1003_STM.h @@ -19,19 +19,16 @@ // STL headers // C headers // Framework headers -#if ARDUINO < 100 -#include -#else -#include -#endif +#include +#include /** * Driver for VS1003 - MP3 / WMA / MIDI Audio Codec Chip * * See http://www.vlsi.fi/en/products/vs1003.html */ -class VS1003_STM +class VS1003 { private: uint8_t cs_pin; /**< Pin where CS line is connected */ @@ -40,7 +37,8 @@ private: uint8_t reset_pin; /**< Pin where RESET line is connected */ uint8_t my_SPCR; /**< Value of the SPCR register how we like it. */ uint8_t my_SPSR; /**< Value of the SPSR register how we like it. */ -protected: + SPIClass my_SPI; +public: inline void await_data_request(void) const { while ( !digitalRead(dreq_pin) ); @@ -82,14 +80,14 @@ protected: */ void loadUserCode(const uint16_t* buf, size_t len) const; -public: +//public: /** * Constructor * * Only sets pin values. Doesn't do touch the chip. Be sure to call begin()! */ - VS1003_STM( uint8_t _cs_pin, uint8_t _dcs_pin, uint8_t _dreq_pin, uint8_t _reset_pin); + VS1003( uint8_t _cs_pin, uint8_t _dcs_pin, uint8_t _dreq_pin, uint8_t _reset_pin, SPIClass _spi = SPIClass(1)); /** * Begin operation diff --git a/STM32F1/libraries/Serasidis_VS1003B_STM/examples/hello_STM/hello_STM.ino b/STM32F1/libraries/Serasidis_VS1003B_STM/examples/hello_STM/hello_STM.ino index e00ad11..a498597 100644 --- a/STM32F1/libraries/Serasidis_VS1003B_STM/examples/hello_STM/hello_STM.ino +++ b/STM32F1/libraries/Serasidis_VS1003B_STM/examples/hello_STM/hello_STM.ino @@ -9,6 +9,7 @@ Home: http://www.serasidis.gr email: avrsite@yahoo.gr + 06 Jun 2015 - Roger Clark, added support for SPI 2 and SPI 3 29 May 2015 - Added a fix for booting the VS1053B boards into mp3 decoding instead of booting into MID (modeSwitch function). */ @@ -16,7 +17,6 @@ #include #include - /* * VS1003 development board connected by it's header pins the following way: * @@ -32,8 +32,6 @@ * 5V - 5V - */ -VS1003_STM player(PC14, PB10, PA8, PA9); // cs_pin, dcs_pin, dreq_pin, reset_pin - static const unsigned char HelloMP3[] = { 0xFF,0xF2,0x40,0xC0,0x19,0xB7,0x00,0x14,0x02,0xE6,0x5C, /* ..@.......\ */ 0x01,0x92,0x68,0x01,0xF1,0x5E,0x03,0x08,0xF0,0x24,0x80, /* ..h..^...$. */ @@ -189,26 +187,29 @@ static const unsigned char HelloMP3[] = { 0x20,0x20,0x20,0x4D,0x50,0x33,0x20,0x48,0x65,0x6C,0x6C, /* MP3 Hell */ 0x6F,0x2C,0x20,0x57,0x6F,0x72,0x6C,0x64,0x21,0x20,0x20, /* o, World! */ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, /* */ - 0x00, /* . */ + 0x00 }; -void setup () { +VS1003 player(PC14, PB10, PA8, PA9); // cs_pin, dcs_pin, dreq_pin, reset_pin, SPI channel - defaults to SPI + +/* Example of how to use the VS21003 attached to SPI 2 +VS1003 player(PC14, PB10, PA8, PA9,SPIClass(2)); // cs_pin, dcs_pin, dreq_pin, reset_pin, use SPI 2 +*/ + +/* Example of how to use the VS21003 attached to SPI 2 +VS1003 player(PC14, PB10, PA8, PA9,SPIClass(3)); // cs_pin, dcs_pin, dreq_pin, reset_pin, use SPI 3 +*/ +void setup () +{ Serial.begin(9600); - while (!Serial) { - ; //Give some time to Serial port to be initiallized. - } - Serial.println("VS1003 test"); - - // initiate a player + Serial.println("VS1003 HelloMP3"); + player.begin(); player.modeSwitch(); //Change mode from MIDI to MP3 decoding (Vassilis Serasidis). - - // set maximum output volume - player.setVolume(0x00); + player.setVolume(0x00); // set maximum output volume } void loop() { - // play hellomp3 flow each 0.5s ;) - player.playChunk(HelloMP3, sizeof(HelloMP3)); - delay(500); -} + player.playChunk(HelloMP3, sizeof(HelloMP3)); // play hellomp3 - this blocks until the player is ready to receive more data + delay(1000); +} \ No newline at end of file