Hi Leute,
habe mal wieder ein seltsames Problem und zwar nutze ich den Atmega32U4
um ein On-Screen-Display zu realisieren. Ich schreibe also ein BAS
Signal. Dazu verwende ich die Funktion des U4´s die USART Schnittstelle
als SPI Master zu verwenden (Ich brauch die andere zur Kommunikation mit
anderen Geräten)
In der while Schleife des Programms wird ein Flag abgefragt. Ist dieses
1 wird angefangen eine Zeile zu schreiben. Das heißt einlesen eines
Bytes und senden per SPI und das ganze 40 mal hintereinander (per while
Schleife).
Das einlesen des Bytes aus einem bestimmten Speicher dauert ungefähr 19
Takte, so, dass ich Lese und sofort danach schreibe ohne darauf zu
Achten ob SPI fertig ist. Da ich jedoch mit 16MHz und SPI Clock auf
fclock/2 gestellt habe sollte SPI spätestens nach 2*8 + 2 = 18 Takten
fertig sein. Dies funktioniert auch super es wird kein Byte ausgelassen.
Vor dieser Prozedur werden per cli() alle Interrupts abgeschalten und im
nachhinein per sei() wieder eingeschalten.
Dieser Programmabschnitt wird also durch ein Flag eingeleitet. Dieses
Flag wird entweder durch einen Timer Interrupt oder einen externen
Interrupt gesetzt.
Nun zum Problem: In dem Modus indem dieses Flag vom externen Interrupt
gesetzt wird scheint es als würden die Bytes aus dem SPI nicht mit dem
gleichen Abstand herauskommen. Das heißt ich schreibe immer nach genau
19 Takten (Taktanzahl ermittelt durch zählen von Takten die jeder
Assemblerbefehl braucht) ins SPI-USART Register jedoch kommen zwei
aufeinanderfolgend Bytes manchmal um 2 Takte verschoben raus. (Messung
per Oszi). Dies geschieht aber wie gesagt nur in dem einen Modus obwohl
bei beiden das gleiche Programm abgearbeitet wird.
Was könnte der Fehler sein? Ist es möglich, dass der Controller
zwischendrin einfach 2 Takte lang was anderes macht? Beim einlesen des
Bytes verwende ich folgende Assembler Befehle:
ADD
ADC
SUBI
SBCI
CPC
CPI
BRNE
MOVW
LD
STS
LPM
nach instruction Set Liste brauchen diese Befehle immer eine konstante
Anzahl an Takten (BRNE in der Schleife wohl immer 2.) Gibt es doch den
Fall, das ein Befehl mehr Takte benötigt?
Hat jemand zumindest irgendwelche Anregungen was ich noch testen könnte?
Bin mit meinem Latein am Ende.
Vielleicht bringt mich das ja auf andere Ideen!!
Wäre super!
Wie ich sehe misst du die Zeit der Impulse die der LM rausgibt. Das
machst du aber nur um zwischen Zeilen und VSyncs zu unterscheiden oder?
Habe mir auch schon überlegt ob es daran liegt, dass der LM zu ungenau
ist und je nach Eingangssignal seine Schwelle mal früher oder später
überschritten wird und deshalb die Zeilen wackeln.
Ist das Signal des LM's genau genug? Habe die Frage allerdings
zurückgestellt, da es so aussieht als würde nicht eine komplette Zeile
wackeln sondern die einzelnen Buchstaben je Spalte unabhängig
voneinander.
Es handelt sich bei mir um ein Projekt, dass leider schon am Ende steht.
Hardware ist bereits vorgegeben, kann also nicht auf anderen Aufbau und
Software switchen. Software funktioniert bisher auch sehr gut. Das
bewegen der Buchstaben ist meine einzige Sorge.
Nochmal die Frage: Können Befehle aus irgendwelchen Gründen mal einen
Takt länger brauchen?
Thomas Frosch schrieb:> Wie ich sehe misst du die Zeit der Impulse die der LM rausgibt. Das> machst du aber nur um zwischen Zeilen und VSyncs zu unterscheiden oder?
Ups, ich habe Dir versehentlich eine alte Version geschickt. Darin habe
ich mir V-Sync selbst gebastelt, weil ich zu blöd war, Rset am richtigen
Pin anzuschließen und daher kein V-Sync bekam.
In der neueren Version wird V-Sync berücksichtigt, Foto und Skizze
enthält diese Drahtbrücke aber noch nicht. Siehe neuen Quelltext.
> Habe mir auch schon überlegt ob es daran liegt, dass der LM zu ungenau> ist und je nach Eingangssignal seine Schwelle mal früher oder später> überschritten wird und deshalb die Zeilen wackeln.
Nein, der LM1881 ist da recht genau. Etwas Jitter kann es durch die
unterschiedliche Interrupt-Response-Time geben, das habe ich aber
dadurch verhindert, dass der Interrupt den AVR immer im Sleep
überrascht. Die übrigen Arbeiten werden grundsätzlich nur außerhalb des
Bildaufbaus erledigt, also immer nach der letzten Zeile, und auch nicht
zuviel auf einmal.
>> Ist das Signal des LM's genau genug?
Ja, ist genau genug.
> Habe die Frage allerdings> zurückgestellt, da es so aussieht als würde nicht eine komplette Zeile> wackeln sondern die einzelnen Buchstaben je Spalte unabhängig> voneinander.
Naja, ich nutze die SPI-Einheit und nicht USART. Diese braucht 16 Takte
zum Ausschieben, das SPDR ist aber erst nach 2 weiteren Takten wieder
beschreibbar. Das war mir aber recht, denn ich habe zusätzliche Takte
eingefügt, um den Zeichenabstand zu vergrößern. Mein OSD wird im
Amateurfunk (ATV-Relais) eingesetzt, da wird große, gut lesbare Schrift
gebraucht. Der Textbereich wurde bewusst auf 10 Zeilen je 32 Zeichen
begrenzt.
>> Es handelt sich bei mir um ein Projekt, dass leider schon am Ende steht.> Hardware ist bereits vorgegeben, kann also nicht auf anderen Aufbau und> Software switchen. Software funktioniert bisher auch sehr gut. Das> bewegen der Buchstaben ist meine einzige Sorge.
Nunja, Du benutzt USART, ich benutze SPI. Inwieweit USART für SPI taugt,
weiß ich nicht, hat mich noch nie interessiert.
>> Nochmal die Frage: Können Befehle aus irgendwelchen Gründen mal einen> Takt länger brauchen?
Da ist mir nichts bekannt, zumindest, was ASM betrifft. Die
Interrupt-Response-Time ist aber variabel, wenn sich die CPU nicht im
Sleep befindet.
Du schreibst von Sperren des Interrupts durch cli() und sei(). Das mache
ich nicht, Interrupt-Aufrufe sind immer erlaubt.
...
Also ich benutze nicht direkt USART. Der Atmega32U4 bietet die
Möglichkeit den UART als zusätzlichen SPI Master zu verwenden. Ich
benötige den normalen SPI noch damit ich das OSD als Slave ansprechen
kann.
Ich benutze auch den Sleep Modus!
Nach langem rumprobieren scheint es, dass wenn man vor dem senden über
die USART-SPI das TXFlag löscht es besser funktioniert! Die Buchstaben
hibbeln nun nicht mehr aufeinander zu. Allerdings hibbelt es trotzdem
weiter. Dies führe ich jedoch eher auf die Syncs einer Zeile zurück.
Ganz sicher kann ich mir dabei aber auch nicht sein. Vorallem wenn du
schreibst das Signal über den LM ist ziemlich genau. Die Frage ist
wieviel Jitter ist für dich wenig?
Ich sehe das Bild in meinem Grafikartenmodus (also nicht OSD sondern
eigene Syncerzeugung) und das steht ohne kleinstes zittern und dann
schalte ich um auf OSD und es jittert etwas. Das nächste ist auch, dass
ich um das Flag zu löschen nun natürlich etwas länger brauche und
dadurch der Abstand zwischen den Buchstaben größer wird. Zudem kann ich
natürlich auch nicht mehr soviel Zeichen in eine Zeile bekommen (Anfangs
42 nun noch 32). Ich lese über einige Pointer aus dem Programmspeicher
da dort das Charset liegt.
Das SPI mehr als 16 Takte braucht ist klar + 2 für das "9te" Pseudo Bit
Also TXC1 aus UCSR1A löschen dann gehts wesentlich besser.
Seltsam ist nur, dass das nur was ausmacht, wenn der externe Interrupt
an ist, ansonsten nicht????
Du hast nicht zufällig ein Video von deinem OSD Bild? mich würde mal
interessieren wie gut dein Jitter ist. Vielleicht bin ich ja nur zu
knausrig. Blöd ist halt der Vergleich zum Grakamodus. Da ists einfach
perfekt.
Thomas Frosch schrieb:> Also ich benutze nicht direkt USART. Der Atmega32U4 bietet die> Möglichkeit den UART als zusätzlichen SPI Master zu verwenden.
Das können die von mir verwendeten AVRs nicht, also kann ich dazu
mangels Erfahrung nichts sagen. Ich werde mich auch nicht mit diesem U4
beschäftigen, da ich ihn nicht auf selbstgeätzte Platinen löten kann.
Man kann eben nicht alles haben...
> Ich> benötige den normalen SPI noch damit ich das OSD als Slave ansprechen> kann.>> Ich benutze auch den Sleep Modus!
Hmmm, das hier liest sich aber anders:
1
In der while Schleife des Programms wird ein Flag abgefragt. Ist dieses
2
1 wird angefangen eine Zeile zu schreiben. Das heißt einlesen eines
3
Bytes und senden per SPI und das ganze 40 mal hintereinander (per while
4
Schleife).
Das sieht bei mir anders aus. Der CPU-Takt ist aufgrund Sleep aus. Die
Zeile wird per Interrupt vom H-Sync-Signal gestartet. Dadurch, dass die
CPU im Sleep war, ist die Interrupt-Response-Time immer gleich. Würde
der Interrupt während der Abarbeitung einer Endlosschleife auftreten, so
wäre die Response-Time variabel, da ja die CPU erst ihren angefangenen
Befehl fertig abarbeitet.
>> Nach langem rumprobieren scheint es, dass wenn man vor dem senden über> die USART-SPI das TXFlag löscht es besser funktioniert! Die Buchstaben> hibbeln nun nicht mehr aufeinander zu. Allerdings hibbelt es trotzdem> weiter. Dies führe ich jedoch eher auf die Syncs einer Zeile zurück.> Ganz sicher kann ich mir dabei aber auch nicht sein. Vorallem wenn du> schreibst das Signal über den LM ist ziemlich genau. Die Frage ist> wieviel Jitter ist für dich wenig?
Der LM1881 arbeitet vermutlich genauer, als es der AVR erfassen kann.
Denn die I/Os und auch die externen Interruprs (zu denen auch ICP zählt)
werden vom Takt gesteuert. Somit wird das Eingangssignal im Takt des
AVRs gerastert. Ein AVR-Takt ist aber immerhin 1/16 der Zeichenbreite.
Somit ist ein Jitter von 1/16 der Zeichenbreite hinzunehmen. Da H-Sync
aber nicht auf das Zeichen wirkt, sondern auf die Pixelzeile, gibt es
keinen Jitter zwischen den Zeichen, sondern zwischen den Zeilen der
Zeichen.
Mit meiner Interrupt-Methode rastere ich auf den Controllertakt, also
1/16 Zeichenbreite. In einer Warteschleife
Label:
sbis pin_x,bit_y ;2 Takte wenn Skip, sonst 1 Takt
rjmp Label ;2 Takte
;Zeile ausgeben...
kann das Signal nur in jedem dritten Takt erfasst werden. Somit erhöht
sich der Jitter auf 3/16 der Zeichenbreite.
>> Ich sehe das Bild in meinem Grafikartenmodus (also nicht OSD sondern> eigene Syncerzeugung) und das steht ohne kleinstes zittern und dann> schalte ich um auf OSD und es jittert etwas. Das nächste ist auch, dass> ich um das Flag zu löschen nun natürlich etwas länger brauche und> dadurch der Abstand zwischen den Buchstaben größer wird. Zudem kann ich> natürlich auch nicht mehr soviel Zeichen in eine Zeile bekommen (Anfangs> 42 nun noch 32). Ich lese über einige Pointer aus dem Programmspeicher> da dort das Charset liegt.
Einige Pointer?
Der AVR hat nur einen Pointer, der aus dem Flash lesen kann, nämlich den
Z-Pointer. Das Charset umfasst 256 Zeichen, diese sind so angeordnet,
dass in jeder 256-Byte-Page eine Pixelzeile aller Zeichen enthalten ist.
Somit entscheidet ZH über die Pixelzeile und ZL über die
(ASCII-)Zeichennummer. Beide Bytes des Pointers werden separat gesetzt,
der Zugriff erfolgt (per LPM) über nur einen Pointer. Da ist nix mit
"lese über einige Pointer aus dem Programmspeicher".
> Das SPI mehr als 16 Takte braucht ist klar + 2 für das "9te" Pseudo Bit>> Also TXC1 aus UCSR1A löschen dann gehts wesentlich besser.> Seltsam ist nur, dass das nur was ausmacht, wenn der externe Interrupt> an ist, ansonsten nicht????
Bei mir ist während der Ausgabe einer Videozeile kein externer Interrupt
an. Der ICP (auch nur ein externer Interrupt mit Zusatzfeatures)
detektiert das H-Sync-Signal, die Ausgabe der gesamten Pixelzeile
erfolgt in seiner ISR. Während der ISR ist der Aufruf weiterer
Interrupts gesperrt, es ist alsi nichts da, was das Timing zwischen den
Zeichen stören könnte.
>> Du hast nicht zufällig ein Video von deinem OSD Bild? mich würde mal> interessieren wie gut dein Jitter ist.
Nein, habe ich nicht. Werde ich auch nicht machen, weil ich keine
Hardware mehr habe und deswegen auch keine neue Hardware aufbauen werde.
Die Hardware habe ich dem Funkamateur übergeben, für den ich das
Programm schrieb. Die Sache ist seit fast 3 Jahren für mich erledigt,
ich brauche selbst weder ein OSD noch eine "Grafikkarte" für AVRs. Denn
ich bastele nicht mit TV, Video und ähnlichen Dingen, das ist einfach
nicht mein Gebiet.
> Vielleicht bin ich ja nur zu> knausrig. Blöd ist halt der Vergleich zum Grakamodus. Da ists einfach> perfekt.
Das ist ja kein Wunder. Da erzeugst Du ja das Timing selbst und musst
kein externes Timing synchronisieren.
Überprüfe doch bitte nochmal, ob (wie Du sagst) die ganzen Zeichen
gegeneinander zittern, oder ob die ganzen Pixelzeilen gegeneinander
zittern. Denn dass die ganzen Zeichen gegeneinander zittern, halte ich
für sehr unwahrscheinlich. Es werden wohl die Pixelzeilen sein, die
Ursache liegt vermutlich in der verschenkten Auflösung aufgrund der
Abfrage in der While-Schleife.
...
Meiner ist auch im Sleep. Ansonsten bekommt man noch ein wesentlich
schlimmeres zittern
Ich konnte es noch nicht testen wie es sich auswirkt wenn ich das TX
Flag lösche, aber davor (und das ist das seltsame) haben sich die
Zeichen tatsächlich zueinander verschoben. Ich ließ mehrere kleine l´s
schreiben und hab diese mit einem Oszi im Signal angesehen. Ab und zu
sind diese um 2 Takte weiter auseinander.
Du hast recht es sind nicht einige Pointer aber einige
Pointeroperationen da ich aus einem Array den Ascii Code lese den ich
anzeigen möchte und dementsprechend mir die Bytes aus dem Charset im
Flash hole.
Ich kann 40x33 Zeichen anzeigen. Und mit:
>>In der while Schleife des Programms wird ein Flag abgefragt. Ist dieses>>1 wird angefangen eine Zeile zu schreiben. Das heißt einlesen eines>>Bytes und senden per SPI und das ganze 40 mal hintereinander (per while>>Schleife).
meinte ich den USART SPI und 40 mal pro Linie dann geht er in den Sleep.
...
Danke für die Antworten. Kann mir also sicher sein, dass es nicht am LM
liegt. Werde nochmal per Oszi testen ob sich die Zeichen immer noch
voneinander weg bewegen. Hab im moment nur keins hier.
Wenn das so wäre, wäre es ganz schön seltsam, denn das würde bedeuten
die USART-SPI Hardware braucht zwischen zwei Bytes ab und zu zwei Takte
länger.
Nach Assembler Code im Programm gibt es in diesem Abschnitt nichts wo er
mal länger brauchen könnte...