SDI Connections:
Connected via 4 pins on VS1053
- MOSI – Master-out, Slave-in. This line carries data from our Arduino to the SPI-controlled device(s);
- MISO – Master-in, Slave out. This line carries data from the SPI-controlled device(s) back to the Arduino;
- SS – Slave-select. This line tells the device on the bus we wish to communicate with it. Each SPI device needs a unique SS line back to the Arduino. This line is LOW when communicating over the bus and high when finished.
- SCK – Serial clock.
VS1053 to Arduino Connections:
- SS – digital 9 (OUTPUT). You can use other digital pins, but 10 is generally the default as it is next to the other SPI pins. 10 is reserved for the MicroSD library so i will use 9
- MOSI – digital 11 - doesn't need to be set
- MISO – digital 12 - doesn't need to be set
- SCK – digital 13 doesn't need to be set
Also Need
- (BSYNC if needed... see modes) - any pin (OUTPUT) - using 2
- DREQ - any pin (INPUT) - using 3
The pins on the Arduino are set. Apparently those digital pins are optimised for SDI and cant be changed.
SPI Arduino Commands
Begin() - wake up the bus
end() - shut down the bus
setBitOrder() - msb Of lsb
setClockDivider()
setDataMode() - using mode0 for this application.
transfer() - transfer the byte, also returns the register value if a read command is used. In this case pass 0xff (all 1's)
Begin() - wake up the bus
end() - shut down the bus
setBitOrder() - msb Of lsb
setClockDivider()
setDataMode() - using mode0 for this application.
transfer() - transfer the byte, also returns the register value if a read command is used. In this case pass 0xff (all 1's)
SPI VS1053 Commands
Read:
First, XCS line is pulled low to select the device.
Then the READ opcode (0x3) is transmitted via the SI line
Then followed by an 8-bit word address. After the address has been read in, any further data on SI is ignored by the chip. The 16-bit data corresponding to the received address will be shifted out onto the SO line.
XCS should be driven high after data has been shifted out.
DREQ is driven low for a short while when in a read operation by the chip. This is a very short time and doesn’t require special user attention.
Then the READ opcode (0x3) is transmitted via the SI line
Then followed by an 8-bit word address. After the address has been read in, any further data on SI is ignored by the chip. The 16-bit data corresponding to the received address will be shifted out onto the SO line.
XCS should be driven high after data has been shifted out.
DREQ is driven low for a short while when in a read operation by the chip. This is a very short time and doesn’t require special user attention.
unsigned short resultvalue = 0;
unsigned char h = 0;
unsigned char l = 0;
Mp3DeselectData(); // BYSNC High
Mp3SelectControl();// CS low
SPI.transfer(VS_READ_COMMAND); //send read command
SPI.transfer(addressbyte); //send register address
//be careful: when read 0xff,dump it,and read agin
//while((h = SPIGetChar())== 0xff);
h = SPIGetChar();
//while((l = VsReadByte())== 0xff);
l = SPIGetChar();
resultvalue = ((h << 8) | l);
Mp3DeselectControl(); // CS High
return resultvalue;
unsigned char SPIGetChar(){
unsigned char returned = SPI.transfer(0xFF); // transfer dummy data
return returned; /* Return the received byte */
}
Write:
First, XCS line is pulled low to select the device.
Then the WRITE opcode (0x2) is transmitted via the SI line
Then followed by an 8-bit word address.
After the word has been shifted in and the last clock has been sent, XCS should be pulled high to end the WRITE sequence.
After the last bit has been sent, DREQ is driven low for the duration of the register update. Wait for DREQ to go high before performing another write.Mp3DeselectData(); // BYSNC High
Mp3SelectControl(); //CS Low
//SPIPutCharWithoutWaiting(VS_WRITE_COMMAND);
SPI.transfer(VS_WRITE_COMMAND);
//delay(1);
SPI.transfer((addressbyte));
SPI.transfer((highbyte));
SPI.transfer((lowbyte));
SPIWait();
Mp3DeselectControl(); //CS Low
This follows the sequnce from the music shield code. In my interpretation of the datasheet CS should be driven low after the words have been transfered as oppose to after DREQ has returned high (signally update is complete)
The issues i faced is controlling the BYSNC Pin. From what I can tell I am using SDI new mode, in which the BSYNC signal is automatically generated. However, all the code examples write a value to this pin before a read or write command. The Music Shield example pulls the pin high as stated in the datasheet, however other examples pull it low.
VS1053 SDI Modes
Two modes available (native and compatibility mode) controlled by SM_SDINEW(11) in MODE(0) register. The modes vary in the way they achieve bit sync.
In native mode:
SM-SDINEW is set to 1 and bit sync is achieved by internally by XDCS. Page 19 on vs1053 datasheet indicates that this is just using the select pin.
In VS1002 native modes (SM NEWMODE is 1), byte synchronisation is achieved by XDCS. The state of XDCS may not change while a data byte transfer is in progress. To always maintain data synchronisation even if there may be glitches in the boards using VS1053b, it is recommended to turn XDCS every now and then, for instance once after every disk data block, just to make sure the host and VS1053b are in sync.
If SM SDISHARE is 1, the XDCS signal is internally generated by inverting the XCS input.
In compatibility mode:
the BSYNC pin is used. BYSNC must be high on the first sample and if left high at the end on the first byte (8 bits) transfer, will cause the receiver to stay active and receive the next byte. Only 1 byte can be transfered at a time. This explains why all the register write example code take 2 paramaters. Each register entry must be sent as two 8-bit words.
When VS1053b is running in VS1001 compatibility mode, a BSYNC signal must be generated to ensure correct bit-alignment of the input bitstream. The first DCLK sampling edge (rising or falling, depending on selected polarity), during which the BSYNC is high, marks the first bit of a byte (LSB, if LSB-first order is used, MSB, if MSB-first order is used). If BSYNC is ’1’ when the last bit is received, the receiver stays active and next 8 bits are also received.
This comment has been removed by the author.
ReplyDeletePin 10 must always be set as output to avoid allowing the Arduino to be set to slave
ReplyDeleteThere is alot of confusion over this process.
ReplyDeleteThe Mp3 Shield example from the spark fun site pulls DCS and CS Low before sending data. This sketch does have an error and had to be modified slightly to get it to upload. As the main loop pulls DCS Low I added the same command to the read and write methods and the code uploads and plays successfully.
On the other hand other playback code from the mac forums pulls the XDCS High before sending data. This is more inline with the VS1053 datasheet however I am confused by the situation.