Unreliable Reset of VS1053

Writing software for systems that use VLSI Solution's devices as slave codecs to a host microcontroller.
dandynstuff
User
Posts: 14
Joined: Mon 2017-03-13 18:51

Unreliable Reset of VS1053

Post by dandynstuff » Wed 2017-03-15 1:38

My VS1053 is controlled by an Arduino. Most of the times it works as it should playing mp3 and wav files, but it seems my reset-routine is not working reliably (9 out of 10 times it works, and then again suddenly it does not work). E.g. I do a reset, then a sine test, then again a reset and play my mp3-file (from SD-card).
But sometimes the reset does not work, then I hear only a click, or nothing, or the music is too fast or too slow. Also it seems there's a problem with setting the CLOCKF-register, since I sometimes need to set it multiple times, until I read back the correct value. It seems the reset-routine I found online and in the datasheet are not the same. Is there an example you suggest using, or what am I doing wrong?

Code: Select all

void reset()
{
  digitalWrite(RESET,LOW);
  delay(100);
  digitalWrite(CS,HIGH);
  digitalWrite(CSD,HIGH);
  digitalWrite(RESET,HIGH);
  delay(100);
  softReset();
  delay(500);
  while(!(regIn(3)==0x6000))
    regOut(3,0x6000);
 
  setVolume(40, 40);
}

void softReset(void)
{
  regOut(0, 0x0804); /* Newmode, Reset, No L1-2 */
  delay(100);
}

void regOut(byte addressbyte, unsigned int value)
{
  byte hb = value / 256;
  byte lb = value % 256;

  while (!digitalRead(READY)) ; //Wait for DREQ to go high indicating IC is available
  digitalWrite(CS, LOW); //Select control
  delay(1);
  //SCI consists of instruction byte, address byte, and 16-bit data word.
  SPI.transfer(0x02); //Write instruction
  SPI.transfer(addressbyte);
  SPI.transfer(hb);
  SPI.transfer(lb);
  while (!digitalRead(READY)) ; //Wait for DREQ to go high indicating command is complete
  digitalWrite(CS, HIGH); //Deselect Control
  delay(1);
}

unsigned int regIn(byte addressbyte)
{
  unsigned int res = 0;
  while (!digitalRead(READY)) ; //Wait for DREQ to go high indicating IC is available
  digitalWrite(CS, LOW); //Select control
  delay(1);
  //SCI consists of instruction byte, address byte, and 16-bit data word.
  SPI.transfer(0x03); //read instruction
  SPI.transfer(addressbyte);
  byte hb = SPI.transfer(0);
  byte lb = SPI.transfer(0);
  res = hb;
  (res <<= 8) |= lb;
  while (!digitalRead(READY)) ; //Wait for DREQ to go high indicating command is complete
  digitalWrite(CS, HIGH); //Deselect Control
  delay(1);
  return res;
}

void sineTest(byte val, int ms)
{
  reset();
  unsigned int mode = regIn(0);
  mode |= 0x0020;
  regOut(0, mode);
  byte data[] = {0x53, 0xEF, 0x6E, 170, 0, 0, 0, 0};
  data[3] = val;
  while (!digitalRead(READY));
  digitalWrite(CSD, LOW);
  delay(1);
  
  for (int i = 0; i < 8; i++)
  {
    while (!digitalRead(READY));
    SPI.transfer(data[i]);
  }
  while (!digitalRead(READY));
  digitalWrite(CSD, HIGH);
  delay(1);
  delay(ms);

  byte data2[] = {0x45, 0x78, 0x69, 0x74, 0, 0, 0, 0};
  while (!digitalRead(READY));
  digitalWrite(CSD, LOW);
  delay(1);
 
  for (int i = 0; i < 8; i++)
  {
    while (!digitalRead(READY));
    SPI.transfer(data2[i]);
  }
  while (!digitalRead(READY));
  digitalWrite(CSD, HIGH);
  delay(1);
  mode = regIn(0);
  mode &= 223;
  regOut(0, mode);
  reset();
}


User avatar
pasi
VLSI Staff
Posts: 1412
Joined: Thu 2010-07-15 16:04

Re: Unreliable Reset of VS1053

Post by pasi » Wed 2017-03-15 13:40

Check that GPIO0 and GPIO1 are pulled low. If GPIO1 is floating while GPIO0 is low, vs1053b could enter real-time MIDI mode (and set CLOCKF on its own, and set rate to 44100Hz), and expected MIDI data through SDI or UART.
Visit https://www.facebook.com/VLSISolution VLSI Solution on Facebook

User avatar
Henrik
VLSI Staff
Posts: 1041
Joined: Tue 2010-06-22 14:10

Re: Unreliable Reset of VS1053

Post by Henrik » Wed 2017-03-15 13:50

Hello!

If you already have problems with setting SCI_CLK (regOut(3,0x6000)), then you have some kind of an SPI communication problem. Please check the following:
1) Max SPI speed is CLKI/7. So, just after the reset, your maximum speed is 12.288 MHz / 7 = 1.75 MHz for SPI. After you have set the clock to 0x6000 = 36.864 MHz, maximum SPI speed is 5.25 MHz.
2) Check SPI polarity. The correct polarity for your microcontroller would be to put data out on the falling clock edge, and read data on rising clock edge. Getting this wrong is common, and often results in a system that almost works: much of the data comes through ok, but there are occasional, persistent errors.
3) Pasi's suggestion above.

What I recommend for you to test is to make a simple program that just writes random values to registers SCI_AICTRL0 - SCI_AICTRL3, then reads them. Make sure they have both values with the most significant data bit set/cleared; that one is the most time-critical and usually the first to fail. When you get that working reliably, your other problems will also probably disappear.

Kind regards,
- Henrik
Good signatures never die. They just fade away.

dandynstuff
User
Posts: 14
Joined: Mon 2017-03-13 18:51

Re: Unreliable Reset of VS1053

Post by dandynstuff » Wed 2017-03-15 18:36

Thanks Pasi, but I'm using this hardware: http://www.bajdi.com/lcsoft-vs1053-mp3-module/, so I cannot influence the gpio-pins. I only have the dreq, CS (sci), Cs (sdi), reset, and the miso/mosi/clk

As far as I understand the SPI, I use these settings: SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));, so actually rather conservative speed, and Mode0 seems to be appropriate, or am I missing something?

Thanks Henrik for the idea of reading/writing to the AICTRL-registers. I wrote 0 to 65535 to all of them and always got the correct reading back, so the SPI seems to be ok... Is there some special timing (min. delay) I need to be aware of, or is waiting for DREQ to go high always sufficient?

User avatar
Henrik
VLSI Staff
Posts: 1041
Joined: Tue 2010-06-22 14:10

Re: Unreliable Reset of VS1053

Post by Henrik » Thu 2017-03-16 12:08

dandynstuff wrote:Thanks Henrik for the idea of reading/writing to the AICTRL-registers. I wrote 0 to 65535 to all of them and always got the correct reading back, so the SPI seems to be ok...
That's weird. All seemed to suggest to me that you had a data reliability issue. But if you can write and read the AICTRL registers without hitches, then that is pretty much ruled out.
Is there some special timing (min. delay) I need to be aware of, or is waiting for DREQ to go high always sufficient?
DREQ high should be enough.

Still, there might be a few things you'd like to optimize in regOut():

Code: Select all

void regOut(byte addressbyte, unsigned int value)
{
  byte hb = value / 256;
  byte lb = value % 256;
   // I don't know about your compiler, but the following might make for smaller and faster code:
   // byte hb = (byte)(value >> 8);
   // byte lb = (byte)(value & 255);

  while (!digitalRead(READY)) ; //Wait for DREQ to go high indicating IC is available
  digitalWrite(CS, LOW); //Select control
  // delay(1); // This delay is unnecessary
  //SCI consists of instruction byte, address byte, and 16-bit data word.
  SPI.transfer(0x02); //Write instruction
  SPI.transfer(addressbyte);
  SPI.transfer(hb);
  SPI.transfer(lb);
  // The following line is not required: you first stop the transaction by turning CS high,
  // and you don't need to check that it has concluded in VS1053 because you always check
  // for DREQ at the beginning of the regIn() / regOut() functions.
  //while (!digitalRead(READY)) ; //Wait for DREQ to go high indicating command is complete
  // Question: From the code of regIn() it looks that SPI.transfer() is a synchronous function, i.e.
  // it always finishes the byte transmission so the CS cannot be deselected while the byte is
  // still being transmitted. Is this assumption correct?
  digitalWrite(CS, HIGH); //Deselect Control
  // delay(1); // This delay is also unnecessary
}
Similar comments on the Delay() functions are also valid for regIn(). Still, none of these things should actually break your code. So, take these suggestions at your own will, and if they break your software, just forget I wrote anything!

Kind regards,
- Henrik
Good signatures never die. They just fade away.

User avatar
pasi
VLSI Staff
Posts: 1412
Joined: Thu 2010-07-15 16:04

Re: Unreliable Reset of VS1053

Post by pasi » Thu 2017-03-16 15:18

dandynstuff wrote:Thanks Pasi, but I'm using this hardware: http://www.bajdi.com/lcsoft-vs1053-mp3-module/, so I cannot influence the gpio-pins. I only have the dreq, CS (sci), Cs (sdi), reset, and the miso/mosi/clk
That Web page does say the LCSoft board is wired for real-time MIDI mode. Have you made any modifications to the board?

The comment section also quotes our workaround of detecting RT-MIDI mode and trying to restart.

“You can detect RTMIDI mode after hardware/software reset by checking AUDATA. If you see 44100/44101, RTMIDI has been activated, and you can write GPIO_DDR=3 and GPIO_ODATA=0, then give software reset to boot into normal decoding mode.”

0xc017->WRAMADDR, 3->WRAM, 0xc019->WRAMADDR, 0->WRAM, then software reset
Visit https://www.facebook.com/VLSISolution VLSI Solution on Facebook

dandynstuff
User
Posts: 14
Joined: Mon 2017-03-13 18:51

Re: Unreliable Reset of VS1053

Post by dandynstuff » Thu 2017-03-16 16:00

Thanks, will definitelly use your optimisation suggestions. Seems I've been spoiled with high-level programming for too long, thus the sloppy implementaion :) The last delay seems necessary to me, since if I have e.g. a write followed by a read, I'd release the cs-line and pull it low immediatelly again, (should wait at least 5 ns after changing cs-line according to the datasheet), but I'll def. reduce it to 1 uS instead of a ms :)
The synchronous function is a very good question, that I'll need to look into, since I'm using the official SPI-Library for the Arduino... Then again it's strange that it only seems to affect the clock-register....
@Pasi: That's a great input, that I'll def. try, although I'd expect it to always or never work, if that was the problem?

dandynstuff
User
Posts: 14
Joined: Mon 2017-03-13 18:51

Re: Unreliable Reset of VS1053

Post by dandynstuff » Thu 2017-03-16 19:21

Seems the idea with the audata-register is a good point, I've now found out, that after resets the register either reads as 8000 or 24001 :o . If it reads as 8000, everything is fine, if it reads as 24001 and I try to communicate with the chip nothing works.
writing GPIO_DDR=3 and GPIO_ODATA=0 does not seem to help though :(

Code: Select all

//Hardware reset of the chip
void reset()
{
  digitalWrite(RESET, LOW);
  delay(100);
  digitalWrite(CS, HIGH);
  digitalWrite(CSD, HIGH);
  digitalWrite(RESET, HIGH);
  delay(100);

  //pasi-solution because of midi
  memWrite(0xc017,3);
  memWrite(0xc019,0);
  softReset();
  delay(500);
  while (!(regIn(3) == 0x6000))
    regOut(3, 0x6000);
  setVolume(40, 40);

  Serial.println(regIn(5));
  
}

void softReset(void)
{
  regOut(0, 0x0804); /* Newmode, Reset, No L1-2 */
  delay(100);
}

//write to chip's memory
void memWrite(unsigned int addr, unsigned int val)
{
  regOut(7, addr);
  regOut(6, val);
}




PS: No, I have not made any modifications to the board.

User avatar
pasi
VLSI Staff
Posts: 1412
Joined: Thu 2010-07-15 16:04

Re: Unreliable Reset of VS1053

Post by pasi » Fri 2017-03-17 11:03

24001 in AUDATA would point to something else than realtime MIDI is being decoded. You can also read out HDAT1 and HDAT0 to see which format the vs1053 thinks it is decoding.

It is possible that communication that is not intended for the serial data interface is still going there. Check that xDCS is high during SCI accesses.

Does this happen after power-up reset or after software reset? Are you using the cancel procedure between files?
Visit https://www.facebook.com/VLSISolution VLSI Solution on Facebook

dandynstuff
User
Posts: 14
Joined: Mon 2017-03-13 18:51

Re: Unreliable Reset of VS1053

Post by dandynstuff » Fri 2017-03-17 20:01

Thanks.
When I have 24001 in AUDATA, I read
HDAT0 = 0
and HDAT1= 1023

This is after Hardware Reset (that also calls Software Reset). Yes I use the cancel between songs, but this seems to work perfectly without any resets... Also my registerOut and In always check for Dreq high, before transferring any data.

Code: Select all

//Hardware reset of the chip
void reset()
{
  digitalWrite(RESET, LOW);
  delay(100);
  digitalWrite(CS, HIGH);
  digitalWrite(CSD, HIGH);
  digitalWrite(RESET, HIGH);
  delay(100);

  //pasi-solution because of midi
  memWrite(0xc017, 3);
  memWrite(0xc019, 0);
  softReset();
  delay(500);
  while (!(regIn(3) == 0x6000))
    regOut(3, 0x6000);
  setVolume(40, 40);

  Serial.println(regIn(5));
  Serial.println(regIn(8));
   Serial.println(regIn(9)); 

}

void softReset(void)
{
  regOut(0, 0x0804); /* Newmode, Reset, No L1-2 */
  delayMicroseconds(2);
  while (!digitalRead(READY));
}
void regOut(byte addressbyte, unsigned int value)
{
  /*
    byte hb = value / 256;
    byte lb = value % 256;
  */

  byte hb = value >> 8;
  byte lb = value & 255;

  while (!digitalRead(READY)) ; //Wait for DREQ to go high indicating IC is available
  digitalWrite(CS, LOW); //Select control
  delayMicroseconds(1);
  //SCI consists of instruction byte, address byte, and 16-bit data word.
  SPI.transfer(0x02); //Write instruction
  SPI.transfer(addressbyte);
  SPI.transfer(hb);
  SPI.transfer(lb);
  //while (!digitalRead(READY)) ; //Wait for DREQ to go high indicating command is complete
  digitalWrite(CS, HIGH); //Deselect Control
  delayMicroseconds(1);
}


Post Reply

Who is online

Users browsing this forum: Bing [Bot]