VS1053 + mSD to run mp3 on its own
Erlend
Posts: 612
To avoid creating all the sounds I need in .wav I had the idea to run mp3 files from a separate board, as instructed through SPI from Prop. Found a nice break-out board at Ada, but maybe I was too fast (again) to add-to-basket, because now I seem to understand that Prop has to do the work of reading SD and feeding into the VS1053 chip. So instead of occasionally shooting off a short 'play file_nnn' SPI command, now a cog is needed to read&write sound data all the time while playing. Will be hard on prop i/o, and will mean a lot of coding to do for me - I already suffer an inbox-overload situation in my life/brain/lab, so this 'household' coding is not something I urge for now.
I searched Obex, but with little luck, so now I ask the Forum for help - maybe someone have already intefaced this breakout board, or at least the VS1053 chip - or maybe there is an other board out there which is doing exactly what I wanted? Or maybe I am wrong about the ada-board - that it can do this after all?
Erlend
I searched Obex, but with little luck, so now I ask the Forum for help - maybe someone have already intefaced this breakout board, or at least the VS1053 chip - or maybe there is an other board out there which is doing exactly what I wanted? Or maybe I am wrong about the ada-board - that it can do this after all?
Erlend

Comments
A better choice for what you're trying to do would be the Daisy player kit, which includes a PIC uC to read the card and simple inputs to trigger playback:
http://www.teuthis.com/daisy/
Or, a bit fancier, smaller, more capable, and pre-assembled, Rogue Robotics uMP3:
http://www.roguerobotics.com/products/electronics/ump3
If you'd like to see an example of a Propeller controlling a similar codec, Harrison Pham's award-winning Thumper does this as well as a lot of other cool network streaming stuff:
http://classic.parallax.com/Thumper/tabid/848/Default.aspx
I will put the ada-player in a drawer for some future project. Both the uMP3 and the Vmusic2 fit my purpose perfectly, but I think I will go for the Vmusic because - I did not think about that before - the USB stick is a more convenient format in this application. The interface looks dead simple, with SPI or serial, and a easy command set.
Erlend
PUB Speak(n) case n 0 : ser.str(2, string("VPF 0.mp3", CR)) waitcnt(40_000_000 + cnt) 1 : ser.str(2, string("VPF 1.mp3", CR)) waitcnt(40_000_000 + cnt) 2 : ser.str(2, string("VPF 2.mp3", CR)) waitcnt(40_000_000 + cnt) PUB SayNumber(num) | x, y, z 'will not say '0' ??? Silence VolUP x := (num/100) * 100 y := ((num/10) // 10) * 10 z := num // 10 If (y+z) > 9 AND (y+z) < 20 z := y + z y~ if x > 0 Silence VolUp speak(x) waitcnt(40_000_000 + cnt) if y > 0 Silence VolUp speak(y) waitcnt(40_000_000 + cnt) if z == 0 if x == 0 AND y == 0 Silence VolUp speak(z) if z > 0 Silence VolUp speak(z) PUB SetVol ser.str(2, string("VSV")) ser.tx(2, $20) ser.tx(2, VoiceVol) ser.tx(2, $0D) PUB Set1033Rate ser.str(2, string("VWR")) ser.tx(2, $20) ser.tx(2, $05) 'sample rate ser.tx(2, 44101) ser.tx(2, 44101 >> 7) ser.tx(2, $0D) PUB Set1033Mode ''unused should be vwr? ser.str(2, string("VRD")) '''v read ser.tx(2, $20) ser.tx(2, Mode) '''MODE=$00, VOL=$0B, STATUS=$01, audata/RATE=$05, BASS=$02 ser.tx(2, Mode >> 8) ser.tx(2, CR) PUB Set1033Bass ser.str(2, string("VWR")) ser.tx(2, $20) ser.tx(2, $02) 'bass ser.tx(2, 1111_1111) ' bass15 14 13 12 booost 1-15 .. freq ser.tx(2, 0001_0001) 'trebel 7654 boost/cut -8..7 0 = off ... freq ser.tx(2, $0D) PUB VolON ser.str(2, string("VSV")) ser.tx(2, $20) ser.tx(2, 00) ser.tx(2, $0D) PUB VolOFF ser.str(2, string("VSV")) ser.tx(2, $20) ser.tx(2, 100) ser.tx(2, $0D) PUB ReadFile(readlen) 'rd4 := readlen >> 24 'rd3 := readlen >> 16 'rd2 := readlen >> 8 'rd1 := readlen 'ser.str(2, string("RDF")) 'ser.tx(2,$20) 'ser.tx(2,rd4) 'ser.tx(2,rd3) 'ser.tx(2,rd2) 'ser.tx(2,rd1) 'ser.tx(2,$0D) PUB OpenFile(filename) 'ser.str(2, string("OPR")) 'ser.tx(2, $20) 'ser.str(2, filename) 'ser.tx(2, $0D) PUB CloseFile(cfname) 'ser.str(2, string("CLF")) 'ser.tx(2, $20) 'ser.str(2, cfname) 'ser.tx(2, $0D) Pub Seek(s) 'seek to a specific location within an already open for read file 'sekval := s 'sekval is long, destination to seek for read start 'go(0,0) 'ser.hex(3, sekval, 4) 'sek4 := sekval >> 24 'sek3 := sekval >> 16 'sek2 := sekval >> 8 'sek1 := sekval 'ser.str(2, string("SEK")) 'ser.tx(2,$20) 'ser.tx(2,sek4) 'ser.tx(2,sek3) 'ser.tx(2,sek2) 'ser.tx(2,sek1) 'ser.tx(2,$0D) PUB OpenFileToWrite(filename) 'open or create file ''''ser.str(2, string("OPW")) 'ser.tx(2, $4F) 'O 'ser.tx(2, $50) 'P 'ser.tx(2, $57) 'W 'ser.tx(2, $20) 'ser.str(2, filename) 'ser.tx(2, $0D) PUB WriteFileSize(size) '4 bytes specifies size of data to follow in WriteData 'wr4 := size >> 24 'wr3 := size >> 16 'wr2 := size >> 8 'wr1 := size 'ser.str(2, string("WRF")) 'ser.tx(2,$20) 'ser.tx(2,wr4) 'ser.tx(2,wr3) 'ser.tx(2,wr2) 'ser.tx(2,wr1) 'ser.tx(2,$0D) PUB WriteData(size, pointer) | g, o 'send the data part of WriteFile 'g~ 'repeat size ''''ser.tx(2, testbyte[g]) 'ser.tx(2, byte[pointer][g]) 'g++ 'ser.tx(2,$0D) PUB readusb(size) | m, v, t, check 't~ 'w(500_000) 'delay required else usb hangs 'm~ 'Repeat until t == size '<<<<<warning flag leave at 64 'v := ser.rxtime(2, 200) ' (z, 100) 'read more, port 0, wait 2 ms if no byte 'If v == -1 'Return -1 'ResponseArray1[m] := v 'm++ 't++ 'if check < 54 'detect/remove previous vinculum response left overs if below first 54 bytes 'if ResponseArray1[m - 3] == $5C 'vinc left over info string 'if ResponseArray1[m - 2] == $3E 'vinc left over info string 'if ResponseArray1[m - 1] == $0D 'vinc left over info string 'm~ 'reset all if old string rec'd 't~ 'reset all if old string rec'd 'check~ 'reset all if old string rec'd ''''''w(100000) 'check++ PUB ReadFileFromUSB(size, startaddr, filename) 'how to set to read if above 64bytes? ''''if size is greater than current file size, device pads FE 'ser.str(3, filename) 'OpenFile(filename) 'if startaddr > -1 'seek(startaddr) 'ReadFile(size) 'read the file at start, using readsize 'readusb(size) 'WritePage(eeprom1, eepromwriteindex, @ResponseArray1, size) 'always store to eeprom1? 'CloseFile(filename) PUB TestUSBReadWRite 'WriteFileToUSB(8, 0,string("logger")) 'waitcnt(40_000_000 + cnt) 'ReadFileFromUSB(8, 0, string("logger")) PUB VStop ser.str(2, string("VST", CR)) ser.tx(2, $0D) PUB VoiceIntro Silence Volup ser.str(2, string("VPF 1005.mp3", CR)) 'Fade PUB VolUp ser.str(2, string("VWR")) ser.tx(2, $20) ser.tx(2, $0B) ser.tx(2, VoiceVol) 'left ser.tx(2, VoiceVol) 'right or vice versa? ser.tx(2, $0D) PUB Reset 'stop playing audio ser.str(2, string("VWR")) ser.tx(2, $20) ser.tx(2, $00) ser.tx(2, ResetMode) ser.tx(2, ResetMode >> 8) 'jump out of wave decode ser.tx(2, $0D) PUB Mute ser.str(2, string("VWR")) ser.tx(2, $20) ser.tx(2, $0B) ser.tx(2, $FE) 'left ser.tx(2, $FE) 'right or vice versa? ser.tx(2, $0D) PUB Silence Mute 'change to fast fade vol off, might be smoother Vstop ResetThanks a bunch for the code!
Erlend
Another SD option:
https://www.sparkfun.com/products/11029
I will buy one! (two, actually).
Erlend
That said, if you're wanting to do much more with any processor you're probably better off getting an all-in-one. The VMusic module is one choice, but there's also others, such as the MP3 Trigger board Sparkfun sells. I've used it and it's painfully easy.
https://www.sparkfun.com/products/11029
Tim
Erlend
To be clear, both Daisy and Rogue Robotics uMP3 have SD sockets and are entirely self-propelled, needing just a command to start playing a song. The uMP3 has its SD socket on the back of the card to make the card smaller. Daisy can be set up to be even simpler to control, where just a pulse or contact closure will trigger playback of an entire song. While all the tools are there to drive a MP3 codec chip from the Propeller, the SD card filesystem will eat a good chunk of Hub RAM just to get the bits out of the file in order.