Forum: Mikrocontroller und Digitale Elektronik VS1011e: es geht, ich habe aber noch ein Problem.


von Luca B. (lucabert)


Lesenswert?

Hallo, nochmal!

Heute nerve ich schon etwas, ich weiß... :D

Also, endlich sieht es so aus, daß das Ding was macht!
Ich habe eine kleine MP3-Datei als Array in dem Code kompiliert und kann 
ich es an den Lautsprecher schicken.

Die Qualität ist SEHR schlecht, es kann aber sein, daß das Problem bei 
dem Lautsprecher ist (ein kleiner, der von einem kaputten PC kommt).
Darüber werde ich mich noch beschäftigen.

Das Problem, jetzt, ist daß ich nicht weiß, wie lange ich warten soll, 
bevor ich eine neue Byte dem VS1011 schicken kann.

Laut Doku sollte ich einfach prüfen, daß DREQ auf 1 ist, praktisch, wenn 
ich keine kurze Pause zwischen den Bytes setzte, wird einfach das Ding 
nicht abspielen.
Und die Länge der Pause ist auch entscheidend, würde ich sagen, denn je 
kürze die Pause ist, desto schneller wird die Datei abgespielt.

Zur Zeit das ist mein Testcode:
1
  vsSetChipSelect();
2
  vsSetBSync();
3
  for(i = 0; i < 2048; i++)
4
    spiWriteByte(0);
5
  for(i = 0; i < 1149;)
6
  {
7
    if(bit_is_set(VS_PIN, VS_DREQ_PIN))
8
    {
9
      spiWriteByte(testMP3[i++]);
10
      _delay_us(450);
11
    }
12
  }
13
  for(i = 0; i < 2048; i++)
14
    spiWriteByte(0);
15
  vsClearBSync();

Meine spiWriteByte-Funktion ist folgende:
1
uint8_t spiWriteByte(uint8_t byte)
2
{
3
  SPDR = byte;
4
  loop_until_bit_is_set(SPSR, SPIF);
5
  return SPDR;
6
}

Und der SPI wird so initialisiert:
1
  SPI_DDR = _BV(MOSI) | _BV(SCK);
2
  SPI_PORT |= _BV(SCK);
3
  SPCR = _BV(SPE) | _BV(MSTR);

Wenn ich die "_delay_us(450);" ändern oder entferne, wird die Datei zu 
schnell abgespielt, oder sogar kommt kein Ton raus denn, ich nehme an!, 
das Ding schafft nicht alles zu dekodieren bevor was neues geschickt 
wird.

Kann jemand mir einen Tipp geben, wie ich vom VS1011 ein Signal bekommen 
kann, so daß ich erst Daten schicke, wenn tatsächlich sie bearbeitet 
werden können?

Oder, kann es sein, daß ich vorher noch was schicken soll, um dem VS1011 
zu sagen, daß die Daten nach einer bestimmten Geschwindigkeit bearbeitet 
werden sollen?
Der Array testMP3 enthält alle Bytes der MP3-Datei, also mehr habe ich 
nicht.

Danke euch nochmal für eure Hilfe!
Luca Bertoncello

von Christoph B. (christophbudelmann) Benutzerseite


Lesenswert?

Vergiss mal deine Delay-Routinen, die sind nicht mehr als ein schlechter 
Work-Around. Wir verwenden nur den VS1053, der aber in der Ansteuerung 
dem VS1011 sehr ähnlich ist. Wenn du den DREQ-Pin korrekt abfragst, 
riskierst du auch keinen Speicherüberlauf auf Seite des VS1011 und deine 
Daten werden, sofern sie korrekt sind, fehlerfrei dekodiert.

Also: Die Abfrage mit DREQ nochmals prüfen, eventuell auch einmal auf 
dem Oszilloskop anschauen, was tatsächlich am Pin vor sich geht.

von Luca B. (lucabert)


Lesenswert?

Christoph Budelmann schrieb:
> Vergiss mal deine Delay-Routinen, die sind nicht mehr als ein schlechter
> Work-Around. Wir verwenden nur den VS1053, der aber in der Ansteuerung

Ich weiß selber, daß diese Delay ein häßliche Workaround ist...
Deswegen habe ich hier gefragt, wie ich diese Workaround mit der 
richtigen Lösung ersetzen kann... :D

> dem VS1011 sehr ähnlich ist. Wenn du den DREQ-Pin korrekt abfragst,
> riskierst du auch keinen Speicherüberlauf auf Seite des VS1011 und deine
> Daten werden, sofern sie korrekt sind, fehlerfrei dekodiert.

so die Theorie. Praktisch sieht es so aus, daß nie gewartet wird...

> Also: Die Abfrage mit DREQ nochmals prüfen, eventuell auch einmal auf
> dem Oszilloskop anschauen, was tatsächlich am Pin vor sich geht.

Ich habe leider keinen Oszi. Ich muß wieder einen Freund fragen, ob er 
seins mir geben kann...
Das werde ich aber bestimmt machen.

Ansonsten, andere Ideen?

Danke
Luca Bertoncello

von Luca B. (lucabert)


Lesenswert?

Christoph Budelmann schrieb:
> Vergiss mal deine Delay-Routinen, die sind nicht mehr als ein schlechter
> Work-Around. Wir verwenden nur den VS1053, der aber in der Ansteuerung
> dem VS1011 sehr ähnlich ist. Wenn du den DREQ-Pin korrekt abfragst,
> riskierst du auch keinen Speicherüberlauf auf Seite des VS1011 und deine
> Daten werden, sofern sie korrekt sind, fehlerfrei dekodiert.
>
> Also: Die Abfrage mit DREQ nochmals prüfen, eventuell auch einmal auf
> dem Oszilloskop anschauen, was tatsächlich am Pin vor sich geht.

Mmmm... vielleicht habe ich was gefunden...

Wenn ich so mache:
1
  vsSetChipSelect();
2
  vsSetBSync();
3
  for(i = 0; i < 1149;)
4
  {
5
    if(bit_is_set(VS_PIN, VS_DREQ_PIN))
6
      spiWriteByte(testMP3[i++]);
7
  }
8
  _delay_ms(1500);
9
  vsClearBSync();

Also, wenn ich warte, bis (vermutlich!) die Datei abgespielt worden ist, 
um den BSync auf 0 zu setzten, dann wird die Datei richtig abgespielt.

Ich muß aber in der Lage sein, ein Signal von dem VS1011 zu bekommen, 
wenn das ganze fertig ist.
Ein "loop_until_bit_is_set(VS_PIN, VS_DREQ_PIN);" anstatt der 
"_delay_ms(1500);" hat leider nichts gebracht.

Wie kann ich den VS1011 fragen, ob er mit dem Abspielen fertig ist?

Danke
Luca Bertoncello

von Dirk B. (sharandac)


Lesenswert?

@Luca Bertoncello,

Es ist zwar schon lange her das ich mit dem VS10XX gespielt habe, aber 
wenn ich mich recht erinnere ist es so gewesen das man die FIFO des 
VS10XX immer nur in 32Byte Blöcken befüllen soll. Der Ablauf sieht wie 
folgt aus:

1. Warten bis DREQ gesetzt ist
2. BSYNC setzen
3. 32 Byte in die FIFO des VS10XX schieben
4. BSYNC löschen
5. Wenn noch nicht alle Daten in den VS10XX geschoben weiter bei 1.
6. Fertig

So in etwas sieht das bei mir aus. Wichtig ist die Reihenfolge und das 
auch wirklich nur 32Byte übertragen werden und danach mit BSYNC das ende 
markiert wird sonst geht das schnell in die Hose.

CA Dirk

von Luca B. (lucabert)


Lesenswert?

Dirk Broßwick schrieb:
> @Luca Bertoncello,
>
> Es ist zwar schon lange her das ich mit dem VS10XX gespielt habe, aber
> wenn ich mich recht erinnere ist es so gewesen das man die FIFO des
> VS10XX immer nur in 32Byte Blöcken befüllen soll. Der Ablauf sieht wie
> folgt aus:
>
> 1. Warten bis DREQ gesetzt ist
> 2. BSYNC setzen
> 3. 32 Byte in die FIFO des VS10XX schieben
> 4. BSYNC löschen
> 5. Wenn noch nicht alle Daten in den VS10XX geschoben weiter bei 1.
> 6. Fertig
>
> So in etwas sieht das bei mir aus. Wichtig ist die Reihenfolge und das
> auch wirklich nur 32Byte übertragen werden und danach mit BSYNC das ende
> markiert wird sonst geht das schnell in die Hose.

Hallo, Dirk

Ich denke, ich habe das Problem gefunden.
Um Strom zu sparen, sowie den Verstärker nicht zu erhitzen, werde ich 
nach dem Abspielen den Verstärker ausschalten.
Wenn ich aber, vom Mikrocontroller, nicht in der Lage bin zu warten, bis 
der VS1011 mit dem Abspielen fertig ist, werde ich einfach dem 
Lautsprecher "ausschalten", obwohl noch Daten vom VS1011 kommen.

Also, jetzt mein Problem ist wirklich einfach zu warten, bis der VS1011 
mit dem Abspielen der Datei fertig ist.
Hat jemand eine Ahnung, wie ich es machen kann?

Besten Dank
Luca Bertoncello

von Christoph B. (christophbudelmann) Benutzerseite


Lesenswert?

Luca Bertoncello schrieb:
> Ich denke, ich habe das Problem gefunden.

Vielleicht solltest du es kurz beschreiben, es werden auch andere Leute 
mit vielleicht ähnlichen Problemen diesen Thread finden.

> Um Strom zu sparen, sowie den Verstärker nicht zu erhitzen, werde ich
> nach dem Abspielen den Verstärker ausschalten.
> Wenn ich aber, vom Mikrocontroller, nicht in der Lage bin zu warten, bis
> der VS1011 mit dem Abspielen fertig ist, werde ich einfach dem
> Lautsprecher "ausschalten", obwohl noch Daten vom VS1011 kommen.
>
> Also, jetzt mein Problem ist wirklich einfach zu warten, bis der VS1011
> mit dem Abspielen der Datei fertig ist.
> Hat jemand eine Ahnung, wie ich es machen kann?

VLSI empfiehlt im Datenblatt des VS1053 die Register HDAT0 und HDT1 
abzufragen, die Informationen über die aktuell wiedergegebene Datei 
enthält. Sind beide 0, wird momentan nichts dekodiert, deine Datei ist 
also komplett wiedergegeben worden.

von Luca B. (lucabert)


Lesenswert?

Christoph Budelmann schrieb:

> Vielleicht solltest du es kurz beschreiben, es werden auch andere Leute
> mit vielleicht ähnlichen Problemen diesen Thread finden.

Ich habe einfach, obwohl es nicht notwendig wäre, den CS auf 1 gesetzt.
Theoretisch hätte dieses Bit schon 1 sein sollen, aber praktisch ohne 
diesen Befehl ging nicht.

Und dazu, mein größstes Problem war, daß ich den Verstärker ausschalte, 
nachdem ich die Daten dem VS1011 geschickt habe, denn ich dachte, wenn 
alle Daten geschickt worden sind, ist auch den Abspielen beendet.
Das war mein Fehler. Der VS1011 arbeitet asynchron...

>> Also, jetzt mein Problem ist wirklich einfach zu warten, bis der VS1011
>> mit dem Abspielen der Datei fertig ist.
>> Hat jemand eine Ahnung, wie ich es machen kann?
>
> VLSI empfiehlt im Datenblatt des VS1053 die Register HDAT0 und HDT1
> abzufragen, die Informationen über die aktuell wiedergegebene Datei
> enthält. Sind beide 0, wird momentan nichts dekodiert, deine Datei ist
> also komplett wiedergegeben worden.

Aha, das ist eine Idee... Ich habe versucht diese zwei Werte zu lesen, 
aber sofort nachdem ich die Daten geschickt habe, und die enthalten alle 
Informationen über die Datei.
Ich werde heute Abend probieren, eine Sekunde zu warten (zur Sicherheit, 
die Datei ist sehr klein!) und sie zu lesen, dann mal sehen, was kommt.

Ich melde mich nochmal, wenn ich den Test gemacht habe!

Besten Dank
Luca Bertoncello

von Christoph B. (christophbudelmann) Benutzerseite


Lesenswert?

Luca Bertoncello schrieb:
> Aha, das ist eine Idee... Ich habe versucht diese zwei Werte zu lesen,
> aber sofort nachdem ich die Daten geschickt habe, und die enthalten alle
> Informationen über die Datei.
> Ich werde heute Abend probieren, eine Sekunde zu warten (zur Sicherheit,
> die Datei ist sehr klein!) und sie zu lesen, dann mal sehen, was kommt.

Vergiss das warten, du musst, nachdem du alle Daten gesendet hast, 
einfach nur so lange die Register auslesen, bis sie 0 sind. Damit hast 
du eine universelle Lösung, egal wie lang deine Datei ist, die bei 
korrekter Implementierung in jedem Fall funktioniert.

von Luca B. (lucabert)


Lesenswert?

Christoph Budelmann schrieb:

> Vergiss das warten, du musst, nachdem du alle Daten gesendet hast,
> einfach nur so lange die Register auslesen, bis sie 0 sind. Damit hast
> du eine universelle Lösung, egal wie lang deine Datei ist, die bei
> korrekter Implementierung in jedem Fall funktioniert.

Ja, ich weiß!

Ich meinte einfach: da ich nicht sicher bin, daß der VS1011e wie der 
VS1053 läuft, werde ich den Test machen, die zwei Daten zu lesen, wenn 
ich weiß, daß die Datei noch abgespielt wird, und wenn ich weiß, daß der 
Abspiel sicher schon beendet ist.

Wird alles wie erwartet funktionieren, werde ich die Lösung so 
implementieren, wie du es beschrieben hast.

Grüße
Luca Bertoncello

von Ulrich P. (uprinz)


Lesenswert?

Der VS1011x kanne ebenso wie der VS105x genutzt werden. Die neueren 
Bausteine verfügen zusätzlich über eine alternative Ansteuerung, die 
Daten und Steuerung über ein SPI Interface ermöglichen.

Der VS10xx bekommt seine Daten immer in Paketen von 32 Bytes, wenn DREQ 
das signalisiert. DREQ muss, wenn ich mich recht erinnere, mit 47..100k 
PullUp auf High gezogen werden. Ein AVR interner PullUp tut es auch.
Allein der VS10xx ist für die Abspielgeschwindigkeit zuständig. Wenn man 
den VS10xx mit einem anderen als den im Datenblatt vorgegebenen Quarz 
betreibt, dann muss man einige Register umstellen, damit die 
Abspielgeschwindigkeit stimmt.

Nur über die internen Register der VS10xx kann man erfahren, ob er mit 
dem Abspielen einer Sequenz fertig ist.

Ich habe mal einen MP3-Player mit einem intern getakteten ATmega32 ( 
also 8MHz) gebaut, der von einer SD-Card abspielt. Ein Delay war in dem 
ganzen Code nicht vorhanden.

Soweit ich weiß, war das BSYNC auch nur einmal am Anfang nötig, um den 
Decoder auf den Bitstrom zu synchronisieren. Danach konnte man es 
getrost auf einem Level liegen lassen. Ich meine, ich hatte das einfach 
mit dem /CS verknüpft, aber das kann ich jetzt nicht beschwören.
Wenn Du Interesse hast, schick mir ne Mail und ich sende Dir den Code.
Abfrage auf Play-Position also aktuelle Abspiel-Position war auch drin.

Gruß, Ulrich

von Luca B. (lucabert)


Lesenswert?

Ulrich P. schrieb:

> Nur über die internen Register der VS10xx kann man erfahren, ob er mit
> dem Abspielen einer Sequenz fertig ist.

Schön, die Frage ist, welcher Register ich abfragen soll... :)
Kannst du es mir sagen?

Danke
Luca Bertoncello

von Christoph B. (christophbudelmann) Benutzerseite


Lesenswert?

Luca Bertoncello schrieb:
> Ulrich P. schrieb:
>
>> Nur über die internen Register der VS10xx kann man erfahren, ob er mit
>> dem Abspielen einer Sequenz fertig ist.
>
> Schön, die Frage ist, welcher Register ich abfragen soll... :)
> Kannst du es mir sagen?

Das Datenblatt hast du aber schon gelesen?!

Auszug aus dem Datenblatt des VS1011, Seite 37:

9.5 Play/Decode
This is the normal operation mode of VS1011e. SDI data is decoded. 
Decoded samples are converted to analog domain by the internal DAC. If 
no decodable data is found, SCI HDAT0 and SCI HDAT1 are set to 0 and 
analog outputs are muted.

HDAT0 und 1 hatte ich aber auch schon genannt.

von Luca B. (lucabert)


Lesenswert?

Christoph Budelmann schrieb:
> Das Datenblatt hast du aber schon gelesen?!
>
> Auszug aus dem Datenblatt des VS1011, Seite 37:
>
> 9.5 Play/Decode
> This is the normal operation mode of VS1011e. SDI data is decoded.
> Decoded samples are converted to analog domain by the internal DAC. If
> no decodable data is found, SCI HDAT0 and SCI HDAT1 are set to 0 and
> analog outputs are muted.
>
> HDAT0 und 1 hatte ich aber auch schon genannt.

Ja, das habe ich auch gelesen... Aber "if no decodable data is found" 
kann man auch lesen "wenn ich Mist schicken".
Von dem Satz würde ich nicht unbedingt verstehen, daß die beide Register 
mit 0 gefüllt werden, wenn die Decodierung beendet ist...

Aber, wie gesagt, ich werde heute Abend ein Test machen!

Grüße
Luca Bertoncello

von Ulrich P. (uprinz)


Lesenswert?

Du musst Dich etwas in die Arbeitsweise des Chips hinein denken. Der 
Decoder läuft immer. Er entnimmt dem Eingangspuffer kontinuierlich Daten 
und schiebt sie in den Decoder. Der Decoder versucht aus den Daten Musik 
zu machen. Wenn ihm das nicht gelingt, setzt er die Status-Flags und 
Mutet.
Es ist für den Decoder unerheblich, ob Du ihm keine oder nicht 
dekodierbare Daten sendest. Du kannst ihm auch eine MP3-Datei mit mega 
großen Album Bildern im Header senden. Das macht ihm nix, er dekodiert 
und verwirft. Wenn dann endlich MP3 Daten kommen, setzt der Decoder den 
neuen Status und macht ein UnMute.

Das ist auch der Grund für die häufige Frage, warum der VS10xx so spät 
erst los spielt bei einigen Dateien. Wenn man einen MP3 Player selber 
programmiert, sollte man tunlichst den Header auswerten und dann erst 
mal bis zu den eigentlichen MP3-Frames 'vorspulen'.

Zur Unterscheidung:
Wenn die Flags SCI HDAT0 und SCI HDAT1 == 0 sind und DREQ anliegt, dann 
ist er am Ende. Ist eine der Bedingungen nicht erfüllt, dann spielt er 
noch.

Es gibt auch eine Application Note in der man erfährt, was man wann am 
besten macht um z.B. die Plopps zwischen den Tracks zu minimieren.
Es macht auf jeden Fall sinn sich mal alle Dokumente auf dem VLSI.fi 
Server anzusehen, die sich auf die VS10xx Serie beziehen. Den Versuch 
meinen Player aus dem FF und ohne weiteres Lesen der AppNotes zu bauen, 
hatte ich nach 3 Tagen basteln verworfen. Dafür war ich dann 1 Abend 
Lesen innerhalb von 2 Abenden Programmieren mit dem Player fertig.

DSPs 'denken' anders als gängige CPUs.

Gruß, Ulrich

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.