Heute habe ich gezwungenermaßen mal die Programme seziert um die Videoausgabe Abläufe zu verfolgen. Eigentlich schließe ich einen Hardwarefehler aus, da die Ports P12 bis P15 bei manueller Programmierung mit Low oder High messbar richtig reagieren.
Ich fange mal mit dem Demo-Programm TV_Text_Demo.spin an weil es im Propeller Forum zum testen empfohlen wurde.
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
OBJ
text : “tv_text”
PUB start | i
‘start term
text.start(12)
text.str(string(13,” TV Text Demo…”,13,13,$C,5,” OBJ and VAR require only 2.8KB “,$C,1))
repeat 14
text.out(” “)
repeat i from $0E to $FF
text.out(i)
text.str(string($C,6,” Uses internal ROM font “,$C,2))
repeat
text.str(string($A,16,$B,12))
text.hex(i++, 8)
Im CON-Block wird die Taktfrequenz des Propeller auf xtal1 (5MHz) x 16 also 80 MHz eingestellt. Im OBJ-Block wird auf eine externe Datei namens TV_Text.spin verwiesen, deren Routinen mit text.ROUTINENNAME aufgerufen werden können.
Dann kommt in der PUB start der wichtige Befehl text.start(12). Es wird also in der externen Datei TV_Text.spin die Routine START mit dem Parameter 12 aufgerufen. Und hier ist die START Routine..
VAR
long col, row, color, flag
word screen[screensize]
long colors[8 * 2]
long tv_status ‘0/1/2 = off/invisible/visible read-only (14 longs)
long tv_enable ‘0/non-0 = off/on write-only
long tv_pins ‘%pppmmmm = pin group, pin group mode write-only
long tv_mode ‘%tccip = tile,chroma,interlace,ntsc/pal write-only
long tv_screen ‘pointer to screen (words) write-only
long tv_colors ‘pointer to colors (longs) write-only
long tv_ht ‘horizontal tiles write-only
long tv_vt ‘vertical tiles write-only
long tv_hx ‘horizontal tile expansion write-only
long tv_vx ‘vertical tile expansion write-only
long tv_ho ‘horizontal offset write-only
long tv_vo ‘vertical offset write-only
long tv_broadcast ‘broadcast frequency (Hz) write-only
long tv_auralcog ‘aural fm cog
OBJ
tv : “tv”
PUB start(basepin) : okay
” Start terminal – starts a cog
” returns false if no cog available
setcolors(@palette)
out(0)
longmove(@tv_status, @tv_params, tv_count)
tv_pins := (basepin & $38) << 1 | (basepin & 4 == 4) & %0101
tv_screen := @screen
tv_colors := @colors
okay := tv.start(@tv_status)
DAT
tv_params long 0 ‘status
long 1 ‘enable
long 0 ‘pins
long %10010 ‘mode
long 0 ‘screen
long 0 ‘colors
long cols ‘hc
long rows ‘vc
long 4 ‘hx
long 1 ‘vx
long 0 ‘ho
long 0 ‘vo
long 0 ‘broadcast
long 0 ‘auralcog
Im OBJ Block wird wieder auf eine TV.spin Datei verwiesen deren Routinen mit tv.ROUTINENNAME aufgerufen werden können. Dann kommt schon die PUB start die den übergebenen Parameter in die Variable basepin übernimmt. Basepin ist der erste der drei Video Ausgangs Ports. Also bei mir 12 gleich Port 12. Soweit alles super.
Interessant wird es wieder beim longmove Befehl. Die Variable tv_count wurde im Programm vorher auf 14 gesetzt. Also werden 14 Longs, zu je 4 Bytes, ab der Speicheradresse @tv_params (ab dort stehen alle Parameter zur TV Ausgabe Einstellung) nach der Speicheradresse @tv_status und folgenden Adressen kopiert. Auch einfach und logisch.
Am Anfang im VAR-Block werden alle TV Einstellungsparameter in Variablen gefasst. Unten im DAT-Block werden ab der Speicheradresse @tv_params Festwerte deklariert, die dann durch den longmove Befehl an die Speicheradressen der Variablen @tv_status kopiert werden. Also werden den Variablen schonmal feste Werte zugwiesen. Auch klar.
Jetzt wird es kompliziert bei dem Befehl tv_pins := (basepin & $38) << 1 | (basepin & 4 == 4) & %0101
Der Wert basepin also 12 wird mit $38 UND verknüpft und einmal nach links geshiftet. Dann wird der Wert basepin mit 4 UND verknüpft und mit 4 verglichen. Das Ergebnis (TRUE also -1 oder False=0) wird mit %0101 UND verknüpft. Das Ergebnis und das Ergebnis der ersten UND Verknüpfung werden oder | verknüpft. Das ergibt dann den Wert für tv_pins
(basepin & $38) << 1 12 %001100 UND $38 %111000 gleich %001000 einmal nach links geschoben gleich %010000
(basepin & 4 == 4) & %0101 12 %1100 UND %0100 gleich %0100 verglichen mit 4 gleich TRUE also -1 (%1111) UND %0101 gleich %0101
%010000 ODER %000101 gleich %010101
Der Wert der Variable tv_pins ist also %0010101
Nun kommt die wichtigste Zeile okay := tv.start(@tv_status)
Damit wird in der externen Datei TV.spin, das ist der TV Treiber, die Routine start mit der ersten Adresse (@tv_status) der Einstellungsvariablen aufgerufen. Also auf in die TV.spin Datei.
PUB start(tvptr) : okay
” Start TV driver – starts a cog
” returns false if no cog available
”
” tvptr = pointer to TV parameters
stop
okay := cog := cognew(@entry, tvptr) + 1
Simpel oder ? Die Startadresse der Einstellungsvariablen wird in die Variable tvptr übernommen. Unten folgt der start eines neuen Cog’s mit der Assembler TV-Treiberroutine. Diese Assembler Routine beginnt bei der Speicheradresse @entry und die Variable tvptr (sprich die Startadresse der 14 Longs für die TV Ausgabe Einstellung) wird im Cog Boot Parameter (PAR) Register des neu gestarteten Cog gespeichert. Auch klar soweit.
Die Assembler Routine ist zu lang um sie hier zu zeigen. Ich zeigen aber mal die Bedeutung des oben errechneten tv_pins Wert. Dieser lautete ja %0010101. Das heißt die Bits 6..4 sind %001 laut der unten stehenden Tabelle würde die %000: pins 15..8 also Pin Group 15..8 vom TV Treiber angesprochen.
Die Bits 3..0 wären %0101 was bedeutet %0101: %0111_0000 baseband
Das bedeutet der Videotreiber erzeugt ein Baseband Signal auf den oberen vier PIN’s also den Ports P12 bis P15. Das wäre ja voll korrekt für meinen Fall, eben eine Composit Videoausgabe ab dem Port 12.
” bits 6..4 select pin group:
” %000: pins 7..0
” %001: pins 15..8
” %010: pins 23..16
” %011: pins 31..24
” %100: pins 39..32
” %101: pins 47..40
” %110: pins 55..48
” %111: pins 63..56
”
” bits 3..0 select pin group mode:
” %0000: %0000_0111 – baseband
” %0001: %0000_0111 – broadcast
” %0010: %0000_1111 – baseband + chroma
” %0011: %0000_1111 – broadcast + aural
” %0100: %0111_0000 broadcast –
” %0101: %0111_0000 baseband –
” %0110: %1111_0000 broadcast + aural –
” %0111: %1111_0000 baseband + chroma –
” %1000: %0111_0111 broadcast baseband
” %1001: %0111_0111 baseband broadcast
” %1010: %0111_1111 broadcast baseband + chroma
” %1011: %0111_1111 baseband broadcast + aural
” %1100: %1111_0111 broadcast + aural baseband
” %1101: %1111_0111 baseband + chroma broadcast
” %1110: %1111_1111 broadcast + aural baseband + chroma
” %1111: %1111_1111 baseband + chroma broadcast + aural
Die Variablen für die TV Einstellungen werden im TV_Text.spin Programm eingestellt. Dort befindet sich ja unten ein DAT-Block der so aussieht.
DAT
tv_params long 0 ‘status
long 1 ‘enable
long 0 ‘pins
long %10010 ‘mode
long 0 ‘screen
long 0 ‘colors
long cols ‘hc
long rows ‘vc
long 4 ‘hx
long 1 ‘vx
long 0 ‘ho
long 0 ‘vo
long 0 ‘broadcast
long 0 ‘auralcog
Die Variable tv_enable wird im DAT-Block auf 1 gesetzt, das bedeutet die Videoausgabe ist enabled also EINGESCHALTET. Die pins werden zwar auf 0 gestellt aber in der TV Treiber Routine wieder umgeschrieben durch die komplizierte Rechnung s.o.
Die Variable mode wird auf %10010 eingestellt. Hier die Bedeutung der Bits.
” tv_mode
”
” bit 4 selects between 16×16 and 16×32 pixel tiles:
” 0: 16×16 pixel tiles (tileheight = 16)
” 1: 16×32 pixel tiles (tileheight = 32)
”
” bit 3 controls chroma mixing into broadcast:
” 0: mix chroma into broadcast (color)
” 1: strip chroma from broadcast (black/white)
”
” bit 2 controls chroma mixing into baseband:
” 0: mix chroma into baseband (composite color)
” 1: strip chroma from baseband (black/white or s-video)
”
” bit 1 controls interlace:
” 0: progressive scan (243 display lines for NTSC, 286 for PAL)
” less flicker, good for motion
” 1: interlaced scan (486 display lines for NTSC, 572 for PAL)
” doubles the vertical display lines, good for text
”
” bit 0 selects NTSC or PAL format
” 0: NTSC
” 3016 horizontal display ticks
” 243 or 486 (interlaced) vertical display lines
” CLKFREQ must be at least 14_318_180 (4 * 3_579_545 Hz)*
” 1: PAL
” 3692 horizontal display ticks
” 286 or 572 (interlaced) vertical display lines
” CLKFREQ must be at least 17_734_472 (4 * 4_433_618 Hz)*
”
” * driver will disable itself while CLKFREQ is below requirement
Der TV Mode wäre für meinen Fall also NTSC, Interlaced, 2x mix chroma into broadcast und 16×32 Pixel tiles. Also NTSC ist schonmal falsch, aber mein Monitor würde bestimmt auch NTSC bewältigen. Der Rest ist OK. Ich habe im TV_Text.spin Programm nun den mode Wert auf %10000 abgeändert. Will heißen PAL, Interlaces usw.
Gebracht hat es null komma nix. Der Propeller gibt einfach kein Signal von sich. Da bin ich ratlos, gebe aber nicht auf.