Assembler VGA Clock generieren

TommyB

Team Bitschubse
17. Mai 2010
2.151
80
48
40
127.0.0.1 ;)
Sprachen
  1. C#
  2. VB.Net
  3. LunaAVR
  4. Assembler
  5. Python
Hiho,

Problem kurz geschildert:
Ich brauche einen VGA Grafikkartensimulator.

Warum ist einfach. Es soll ein alter Monitor recycelt werden. Gebrochenes TFT, ist aber egal, weil es nur um die Leuchtfläche dahinter geht.
Blöd dabei #1: Die Hintergrundbeleuchtung ist eng mit dem Controller verbunden, einfach Spannung anlegen fällt also flach.
Blöd dabei #2: Es funktioniert zwar alles, aber der Monitor geht nach einiger Zeit in den Standby, weil kein Signal.

Soweit ich gelesen habe müssen HSync und VSync erstellt werden und 5V angelegt werden. Anzeige ist ja egal, wird eh nichts angezeigt werden, also R, G und B auf 0.

Jetzt bin ich auf dieses Projekt gestoßen. Klingt vielversprechend, auch wenn es für mich unnötig wohl Bilder ausgibt. Aber ich bin etwas irritiert, ich hatte gelesen dass die Pixel Clock 25,dickemilch MHz ist bei 640x480, der Tiny wird aber mit 20MHz befeuert... Irgendwo muss ich da einen Denkfehler haben.

Was der Tiny für eine Auflösung vorgaukelt ist egal, es soll nur den Standby verhindern.
 
Zuletzt bearbeitet:
Der Tiny wird wahrscheinlich eine interne PLL haben, die es ermöglicht diese Frequenz zu realisieren.
Gerade gesehen das dass ein "2313" ist, der dürfte keine "PLL" haben. Würde mich auch mal interessieren.
 
Zuletzt bearbeitet:
Hi Tommy,

einen Pixelclock hast du dort nicht. Es gibt ein VSync und ein HSync. Kritisch ist das HSync, weil kürzer. Dieses liegt aber bei etwas über 30us Periodendauer.
Bei HSync high wird das analoge Videosignal dargestellt, was du nicht benötigst.

:ciao:
 
VSync = Vertikale Synchronisation?
HSync = Horizontale Synchronisation?

Wozu sind dann die 25MHz?
 
Ja.

Also wenn ich dich jetzt richtig verstehe... Moment, anders.
Ich dachte HSync clockt die Pixel (~25MHz) und VSync die Zeilen.
Heißt das jetzt dass HSync den Zeilenüberlauf darstellt und VSync die Bildwiederholrate (60hz) ist?
 
Heißt das jetzt dass HSync den Zeilenüberlauf darstellt und VSync die Bildwiederholrate (60hz) ist?

Ja, ich denke schon ...

Diese 480 HSyncs sind 480 Zeilen
Mit den nicht dargestellten Zeilen sind es 525 Zeilen.
upload_2018-3-21_19-46-57.png
 
Hmmm. Denn wäre es also nur ein Timer der einen Pin mit 25µs toggelt (HSync). Im Overflow reicht es bis zu 525 zu zählen und die 2 letzten Impulse Low zu ziehen (VSync), das wars schon. ?
Denn kann ich auch n kleineren Tiny nehmen, so viele Pins brauch ich ja nicht, passt denn in n D-Sub Gehäuse.
 
Ok, die Übertragung irgendwelcher Bilddaten interessiert Dich nicht - Du willst eh nur das Backlight aktiv halten.
Mal folgende Überlegungen eingeworfen:
  • VSync soll 60 Hz sein, dummerweise mit 2 von 525 Zyklen low
  • HSync ist 525mal so schnell, also 31,5kHz
Wenn Du einen 8Mhz-Takt durch 256 teilst, landest Du bei 31,25kHz - wäre von der Toleranz her einen Versuch wert gewesen (Tiny mit internem 8Mhz-Takt, Main Clock Prescaler auf 256, Clock Out aktiviert).
Ggf kann man mit OSCCAL noch etwas rausholen...
Für VSync wird ein 16Bit-Timer auf 524 (Plus Überlauftakt = 525) getrimmt, und im PWM verwendet (mit 1(+1) Duty).

Sollte sich mit 'nem ATtiny4/5/9/10 (komplett im Hintergrund) machen lassen - allerdings würden an CLKOUT während des PowerUps 1MHz statt der 31,25kHz anliegen...

der einen Pin mit 25µs toggelt (HSync)
Nein. die 25µs ist die Zeit(-dauer), die das analoge Video-Signal 5,66µs nach der (fallenden ? ) Flanke von HSync haben darf - zusammen 30,66µs der HSync-Periodendauer von 31,75µs
Interessiert Dich nicht...
 
Zuletzt bearbeitet:
Das war so ungefähr auch meine Idee.
Nur mit den 4/5/9/10 is blöd, die kann mein Drachen nicht. Ich dachte da eher an den 13er. Wobei der nur einen Prescaler /8 hat.
Osccal hatte ich ja eh schon mal auf dem Plan vor langer Zeit. Naja, genug Messgeräte habe ich ja mittlerweile hier. Try'n'error.

Während PowerUp, ich glaube das wäre kein Problem. Das Display wird wohl eh auch seine Zeit zum aufwachen brauchen. Vermutlich wesentlich mehr als ein Tiny.
 
Da es lediglich darum geht, VSync und HSync zu erzeugen damit der Monitor nicht ausschaltet, und der Mikrocontroller wahrscheinlich sonst nichts "machen" muss, sollte es doch auch einfach über Portpinzugriffe mit Pausezeiten gehen.
Das Timing muss man sicher nicht exakt einhalten. Der MC sollte dann schon mit 16MHz laufen, damit man unter 100ns Maschinenzyklus kommt. Je kürzer der Maschinenzyklus, desto genauer bekommt man es hin.
Da könnte man irgendeinen AVR Mikrocontroller verwenden mit zwei freien IO Pins. Es wäre eine simple Lösung.
 
4/5/9/10 is blöd
Hab ich mir schon gedacht...
Statt des 13 würde ich den 25/45 empfehlen. Welcher Tiny noch Clockout kann, weiß ich grad nicht. Die 25er können mit der PLL intern mit 16MHz takten und einen der beiden Timer mit 64MHz takten.
Wenn man da wegen 8Bit nicht hin kommt, kann man gemäß Dirk ja immer noch zu Fuß gehen...
Den 25 kannst Du als 150er SOIC (die schmalen), den 45 als TSSOP haben.

Tiny10 und Tiny25 hätte ich hier - passen auch grad noch so in'nen Luftpolsterumschlag;-)
 
So, erstes Proof of concept. Mangels Buchse aber noch ungetestet.
Die i2c Leitungen habe ich nicht angeschlossen, ich weiß noch nicht an welcher Seite die PullUps sitzen. Sollte eigentlich nicht stören.
Ist jetzt mit einem ATtiny13A und internen 9,6MHz, laut Simulator komm ich schon recht nahe an die Timings ran. Bissl Feintuning im OSCCAL falls nötig.



CodeBox Assembler
/* 

    VGASim V1.0 BETA
    ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
    Simulates a VGA signal (generates the clock impulses) to
    not let the monitor go into sleep mode.

    (C) tightDev.Net 2018



    Wireing: ATtiny13A
    ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
                 ___  ___
                |o  \/   |
      ISP Reset |        | +5V
             nc |        | ISP SCK
             nc |        | ISP MISO / VSync
            GND |        | ISP MOSI / HSync
                |________|



    Wireing: VGA
    ¯¯¯¯¯¯¯¯¯¯¯¯
      Pin 1, 2, 3: RGB signals. Unused, connected to GND. Can be 0.7V for white.
      Pin 5, 6, 7, 8, 10: GND
      Pin 13: HSync
      Pin 14: VSync
      Pin 4, 11, 12, 15: not connected
   
*/



// Setup environment
.INCLUDE <tn13Adef.inc>            ; Include chip defination
.EQU SyncDDR    = DDRB            ; The port where the sync lines are connected to
.EQU SyncPort    = PORTB            ; The port where the sync lines are connected to
.EQU SyncPin    = PINB            ; The port where the sync lines are connected to
.EQU HSync        = PINB0            ; Pin used for horizontal sync (31.777557100298 µS)
.EQU VSync        = PINB1            ; Pin used for vertical sync (16.683217477656 mS)
.EQU Reload        = 37            ; Timer reload value for HSync generation
.EQU Calib        = 128            ; Calibration of the internal RC clock



// Define registers
.DEF Temp1        = R16            ; General purpose temp register (not for ISR)
.DEF CntL        = R30            ; Counter register, high byte
.DEF CntH        = R31            ; Counter register, low byte



// Interrupt vector table
.ORG 0x0000        RJMP Init        ; Start of application
.ORG INT0addr    RETI            ; External Interrupt 0
.ORG PCI0addr    RETI            ; External Interrupt Request 0
.ORG OVF0addr    RETI            ; Timer/Counter0 Overflow
.ORG ERDYaddr    RETI            ; EEPROM Ready
.ORG ACIaddr    RETI            ; Analog Comparator
.ORG OC0Aaddr    RCALL OnOC0A    ; Timer/Counter Compare Match A
.ORG OC0Baddr    RETI            ; Timer/Counter Compare Match B
.ORG WDTaddr    RETI            ; Watchdog Time-out
.ORG ADCCaddr    RETI            ; ADC Conversion Complete
.ORG INT_VECTORS_SIZE            ; End of table



// Controller initialization
Init:

    // Set port pins to output and high
    LDI        Temp1,        (1<<HSync) | (1<<VSync)
    OUT        SyncDDR,    Temp1
    OUT        SyncPort,    Temp1

    // Setup power saving: Idle mode, because we need the timer
    LDI        Temp1,        (1<<SE)
    OUT        MCUCR,        Temp1

    // Setup power saving: Disable analog comperator
    LDI        Temp1,   (1<<ACD)|(1<<ACI)
    OUT        ACSR,        Temp1    ; apply and wait 2 cycles
    NOP
    NOP
    OUT        ACSR,        Temp1    ; twice to ensure no interrupt has fired

    // Setup watchdog (1 second)
    CLI                            ; Disable interrupts
    IN        Temp1,        WDTCR
    ORI        Temp1,         (1<<WDCE) | (1<<WDE)
    OUT        WDTCR,        Temp1
    LDI        Temp1,        (1<<WDE) | (1<<WDP2) | (1<<WDP0)
    OUT        WDTCR,        Temp1
    SEI                            ; Enable interrupts

    // Setup Timer (CTC, Clock/8, Interrupt)
    LDI        Temp1,        (1<<WGM01)
    OUT        TCCR0A,        Temp1
    LDI        Temp1,        (1<<CS01)
    OUT        TCCR0B,        Temp1
    LDI        Temp1,        Reload
    OUT        OCR0A,        Temp1
    LDI        Temp1,        (1<<OCIE0A)
    OUT        TIMSK0,        Temp1

    // Reset counter
    LDI        CntH,        0
    LDI        CntL,        0

    // Set maximum values for row counter
    LDI        XH,            HIGH(523)
    LDI        XL,            LOW(523)
    LDI        YH,            HIGH(525)
    LDI        YL,            LOW(525)

    // Tweak the internal RC clock to match the frequencies
//    LDI        Temp1,        Calib
//    OUT        OSCCAL,        Temp1

// RJMP Main                    ; Not required, it's the next command



// Main application loop
Main:

    // Nothing in here, fall asleep and kick the dog after interrupt
    SLEEP
    WDR

RJMP Main



// Interrupt Routine: Compare Match A
OnOC0A:

    // Line is now completed, so toggle HSync
    SBI        SyncPin,    HSync    ; Toggle HSync

    // Increment counter to process VSync
    ADIW    CntH:CntL,    1        ; Increment line counter

    // Check HSync impulse
    CP        CntL,        XL        ; Compare low byte
    CPC        CntH,        XH        ; Compare high byte
    BRLO    OnOC0A_Exit            ; Exit if lower

    // VSync overflow, reset pin
    CBI        SyncPort,    HSync    ; Set pin low

    // Check VSync length
    CP        CntL,        YL        ; Compare low byte
    CPC        CntH,        YH        ; Compare high byte
    BRLO    OnOC0A_Exit            ; Exit if lower

    // VSync signal long enough, set pin and reset counter
    SBI        SyncPort,    HSync    ; Set pin high
    CLR        CntH                ; Reset counter (high byte)
    CLR        CntL                ; Reset counter (low byte)

  OnOC0A_Exit:

RETI
 
Hmm...
Der Timer generiert im CTC 'ne Zeitbasis, im IRQ toggelst Du HSync. Das kann der Timer auch selbst in Hardware machen (Compare Output Mode = &B01).
Zeitbasis: 9600000Hz/8 (Prescaler) = 1,2MHz Timertakt. Nach 38 Timertakten hast Du zwar die 31,666 µS (31,58kHz) - allerdings toggelst Du ja den Pin. Effektiv hast Du da also ca 15kHz).
Du kannst Statt des CTC aber auch fastPWM nutzen, OC0B dann bei 18...

Dein Zeilenzähler zählt von 1..525, zwei Perioden (und ein paar Takte) lang ist HSync (-> müßte VSync sein) gelöscht.
Du kannst Dir einen der Vergleiche sparen, indem Du den Zähler von -525 gegen 0 laufen läßt - wenn der Zähler durch ADIW 0 erreicht, wird automatisch das Z gesetzt;)
 
Oops, ja, toggeln... Aber mit den Frequenzen bin ich eh noch nicht durch, der Simulator will mich verarschen...
Im Einzelschritt geht es, mit BreakPoints nicht 0.o

Auf die Idee mit rückwärts zählen war ich noch nicht gekommen, aber hast recht ;)
 
Du mußt schon vorwärts zählen wenn Du ADIW nimmst, da die Konstante nur sechs Bit "groß" ist. Aber Du mußt ja nicht bei null beginnen. Alter Assembler-Trick...
Wenn's zeitkritisch ist, kann man statt zwei LDI ein MOVW verwenden, kostet allerdings zwei weitere Register.

Breakpoints hab ich im Simulator noch nie genutzt - höchstens mal Run to Cursor.
 
Falls es wer ergoogelt, hier wird das Timing sehr schön beschrieben (Englisch)
 
Und hier mit Bild. Nette Herangehensweise. Unpraktisch, aber interessant.
 
Sehr schön. Elektronik zum Anfassen. ;)

Hier baut er einen kompletten 8-bit-Prozessor aus TTL-Bausteinen.
 
Da sieht man mal wieder, was man mit Breadboards alles anfangen kann. ;)

Nichts gegen
Dino'sche Fädeldrahttechnik
Dino hat‘s erfunden? ;) Meinen ersten Fädelstift habe ich vor über 35 Jahren gekauft. Damit kriege ich heute immer noch den ersten funktionsfähigen Prototypen schneller fertig, als das Layout (wenn ich denn überhaupt noch eins mache).

Aber so ein Projekt sieht doch auf Breadboards einfach viel besser aus, das macht mehr her und darauf kommt‘s bei den Utube-Videos doch an. ;)
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)