916 lines
37 KiB
Plaintext
916 lines
37 KiB
Plaintext
''***************************************
|
||
''* TV Driver v1.1 *
|
||
''* Author: Chip Gracey *
|
||
''* Copyright (c) 2004 Parallax, Inc. *
|
||
''* See end of file for terms of use. *
|
||
''***************************************
|
||
|
||
' v1.0 - 01 May 2006 - original version
|
||
' v1.1 - 17 May 2006 - pixel tile size can now be 16 x 32 to enable more efficient
|
||
' character displays utilizing the internal font - see 'tv_mode'
|
||
{
|
||
2009
|
||
May
|
||
11 Moved blank line tasks into one-time initialization section.
|
||
Difficulty: one task was flipping the interlace bit of _mode, necessitating a reload of _mode
|
||
every superfield. Removed the flip and changed the sense of the Z tests that depended on _mode<1>
|
||
being flipped.
|
||
12 Implemented simple scrolling terminal output in background task.
|
||
Difficulty: have to keep Z clear so that mainline interlaced code works properly.
|
||
June
|
||
9 Added "D"isable and "E"nable commands.
|
||
20 Changing ping response to include basepin.
|
||
}
|
||
|
||
CON
|
||
|
||
fntsc = 3_579_545 'NTSC color frequency
|
||
lntsc = 3640 'NTSC color cycles per line * 16
|
||
sntsc = 624 'NTSC color cycles per sync * 16
|
||
|
||
fpal = 4_433_618 'PAL color frequency
|
||
lpal = 4540 'PAL color cycles per line * 16
|
||
spal = 848 'PAL color cycles per sync * 16
|
||
|
||
paramcount = 14
|
||
' colortable = $180 'start of colortable inside cog
|
||
|
||
cols = 40
|
||
rows = 13
|
||
|
||
VAR
|
||
long cog
|
||
long rendezvous
|
||
|
||
PUB start(basepin, rv) | okay
|
||
|
||
'' Start TV driver - starts a cog if necessary
|
||
'' returns true if it had to start a cog, false if cog was already running.
|
||
''
|
||
_basepin := basepin
|
||
rendezvous := rv
|
||
long[rendezvous]~~ ' ping the sxtv cog (send -1)
|
||
waitcnt( clkfreq/10 + cnt )
|
||
if long[rendezvous] <> -1 ' if the cog is alive it'll set this to _basepin<<8
|
||
long[rendezvous]~
|
||
return false
|
||
|
||
_pins := (basepin & $38) << 1 | (basepin & 4 == 4) & %0101
|
||
|
||
if cog := cognew(@entry, rendezvous) + 1
|
||
return true
|
||
else
|
||
abort string("Couldn't start sxtv cog")
|
||
|
||
PUB stop
|
||
|
||
'' Stop TV driver - frees a cog
|
||
|
||
if cog
|
||
cogstop(cog~ - 1)
|
||
|
||
PUB GetBasepin
|
||
repeat while long[rendezvous]
|
||
long[rendezvous]~~ ' ping the sxtv cog (send -1)
|
||
repeat while long[rendezvous] == -1
|
||
return long[rendezvous]~ >> 8
|
||
|
||
PUB str(stringptr)
|
||
|
||
'' Print a zero-terminated string
|
||
|
||
repeat strsize(stringptr)
|
||
out(byte[stringptr++])
|
||
|
||
|
||
PUB dec(value) | _i
|
||
|
||
'' Print a decimal number
|
||
|
||
if value < 0
|
||
-value
|
||
out("-")
|
||
|
||
_i := 1_000_000_000
|
||
|
||
repeat 10
|
||
if value => _i
|
||
out(value / _i + "0")
|
||
value //= _i
|
||
result~~
|
||
elseif result or _i == 1
|
||
out("0")
|
||
_i /= 10
|
||
|
||
|
||
PUB hex(value, digits)
|
||
|
||
'' Print a hexadecimal number
|
||
|
||
value <<= (8 - digits) << 2
|
||
repeat digits
|
||
out(lookupz((value <-= 4) & $F : "0".."9", "A".."F"))
|
||
|
||
|
||
PUB bin(value, digits)
|
||
|
||
'' Print a binary number
|
||
|
||
value <<= 32 - digits
|
||
repeat digits
|
||
out((value <-= 1) & 1 + "0")
|
||
|
||
|
||
pub out( c )
|
||
repeat while byte[rendezvous]
|
||
byte[rendezvous] := c
|
||
|
||
DAT
|
||
|
||
'*******************************
|
||
'* Assembly language TV driver *
|
||
'*******************************
|
||
|
||
org
|
||
'
|
||
'
|
||
' Entry
|
||
'
|
||
entry
|
||
call #init
|
||
mov taskptr,#tasks 'reset tasks
|
||
|
||
'
|
||
'
|
||
' Superfield
|
||
'
|
||
superfield
|
||
|
||
test _mode,#%0001 wc 'if ntsc, set phaseflip
|
||
if_nc mov phaseflip,phasemask
|
||
|
||
test _mode,#%0010 wz 'get interlace into nz
|
||
mov temp, #0 wz ''' I messed something up and now Z has to be set, not clear.
|
||
'
|
||
'
|
||
' Field
|
||
'
|
||
field mov x,vinv 'do invisible back porch lines
|
||
:black call #hsync 'do hsync
|
||
waitvid burst,sync_high2 'do black
|
||
jmpret taskret,taskptr 'call task section (z undisturbed)
|
||
djnz x,#:black 'another black line?
|
||
|
||
' wrlong visible,par 'set status to visible
|
||
|
||
mov x,vb 'do visible back porch lines
|
||
call #blank_lines
|
||
|
||
|
||
|
||
|
||
mov y,_vt 'set vertical tiles
|
||
movs :getchars4, #text '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||
:line
|
||
mov vx,_vx 'set vertical expand
|
||
mov t1,#32
|
||
mov chset, chset0
|
||
:vert
|
||
if_z xor interlace,#1 'interlace skip?
|
||
if_z tjz interlace,#:skip
|
||
|
||
call #hsync 'do hsync
|
||
|
||
mov vscl,hb 'do visible back porch pixels
|
||
xor tile,colortable
|
||
waitvid tile,#0
|
||
|
||
mov x,_ht 'set horizontal tiles
|
||
shr x, #2 'divide by 4
|
||
|
||
mov vscl,hx 'set horizontal expand
|
||
|
||
:getchars4 mov chars4, 0-0
|
||
mov t3, #4
|
||
:loop4
|
||
mov char, chars4
|
||
ror chars4, #8
|
||
and char, #$ff
|
||
shr char, #1 wc
|
||
shl char, #7
|
||
add char, chset
|
||
rdlong pixels16, char
|
||
' xor colors4, phaseflip
|
||
if_nc waitvid colortable, pixels16
|
||
if_c waitvid colortable+1, pixels16
|
||
djnz t3, #:loop4
|
||
add :getchars4, #1
|
||
djnz x, #:getchars4
|
||
|
||
mov vscl,hf 'do visible front porch pixels
|
||
mov tile,colortable'phaseflip
|
||
' xor tile,colortable
|
||
waitvid tile,#0
|
||
sub :getchars4, #10
|
||
|
||
:skip
|
||
add chset, #4
|
||
djnz t1, #:vert
|
||
|
||
add :getchars4, #10
|
||
djnz y,#:line 'another tile line?
|
||
|
||
if_z xor interlace,#1 wz 'get interlace and field1 into z
|
||
|
||
test _mode,#%0001 wc 'do visible front porch lines
|
||
mov x,vf
|
||
if_nz_and_c add x,#1
|
||
call #blank_lines
|
||
|
||
' if_z wrlong invisible,par 'unless interlace and field1, set status to invisible
|
||
|
||
if_z_eq_c call #hsync 'if required, do short line
|
||
if_z_eq_c mov vscl,hrest
|
||
if_z_eq_c waitvid burst,sync_high2
|
||
if_z_eq_c xor phaseflip,phasemask
|
||
|
||
call #vsync_high 'do high vsync pulses
|
||
|
||
movs vsync1,#sync_low1 'do low vsync pulses
|
||
movs vsync2,#sync_low2
|
||
call #vsync_low
|
||
|
||
call #vsync_high 'do high vsync pulses
|
||
|
||
if_nz mov vscl,hhalf 'if odd frame, do half line
|
||
if_nz waitvid burst,sync_high2
|
||
|
||
if_z jmp #field 'if interlace and field1, display field2
|
||
jmp #superfield 'else, new superfield
|
||
'
|
||
'
|
||
' Blank lines
|
||
'
|
||
blank_lines call #hsync 'do hsync
|
||
|
||
xor tile,colortable 'do background
|
||
waitvid tile,#0
|
||
|
||
djnz x,#blank_lines
|
||
|
||
blank_lines_ret ret
|
||
'
|
||
'
|
||
' Horizontal sync
|
||
'
|
||
hsync test _mode,#%0001 wc 'if pal, toggle phaseflip
|
||
' if_c xor phaseflip,phasemask
|
||
|
||
mov vscl,sync_scale1 'do hsync
|
||
mov tile,burst'phaseflip
|
||
' xor tile,burst
|
||
waitvid tile,sync_normal
|
||
|
||
mov vscl,hvis 'setup in case blank line
|
||
mov tile,#0'phaseflip
|
||
|
||
hsync_ret ret
|
||
'
|
||
'
|
||
' Vertical sync
|
||
'
|
||
vsync_high movs vsync1,#sync_high1 'vertical sync
|
||
movs vsync2,#sync_high2
|
||
|
||
vsync_low mov x,vrep
|
||
|
||
vsyncx mov vscl,sync_scale1
|
||
vsync1 waitvid burst,sync_high1
|
||
|
||
mov vscl,sync_scale2
|
||
vsync2 waitvid burst,sync_high2
|
||
|
||
djnz x,#vsyncx
|
||
vsync_low_ret
|
||
vsync_high_ret ret
|
||
'
|
||
'
|
||
' Tasks - performed in sections during invisible back porch lines
|
||
'
|
||
tasks
|
||
|
||
clearscreen
|
||
mov i, #14 ' clear 13 lines + 1 extra to make scrolling easier
|
||
:lines
|
||
mov j, #40/4 ' 40 columns, 4 chars at a time
|
||
:chars
|
||
:storem mov text, x20202020
|
||
add :storem, d0 ' inc dst
|
||
djnz j, #:chars
|
||
jmpret taskptr,taskret
|
||
djnz i, #:lines
|
||
|
||
waitforchar
|
||
mov temp, #0 ' clear buffer: ready to accept next byte
|
||
wrlong temp, par
|
||
waitnoclear
|
||
:wait
|
||
jmpret taskptr,taskret
|
||
|
||
rdlong ch, par
|
||
tjz ch, #:wait
|
||
' got a byte
|
||
|
||
mov temp, cmdPing ' roundabout comparisons to avoid changing Z.
|
||
sub temp, ch ' ch = -1 is just a ping to see if this cog is alive.
|
||
tjz temp, #ping
|
||
mov temp, cmdDisable
|
||
sub temp, ch
|
||
tjz temp, #disable
|
||
mov temp, cmdEnable
|
||
sub temp, ch
|
||
tjz temp, #enable
|
||
neg temp, #256 ' at this point, if ch is > 255, it must be _basepin<<8
|
||
and temp, ch ' as set by a previous ping, so we just ignore it
|
||
tjnz temp, #waitnoclear ' (leave the long pointed to by par undisturbed).
|
||
|
||
:char
|
||
mov temp, #8
|
||
sub temp, ch
|
||
tjz temp, #:bksp
|
||
mov temp, #13
|
||
sub temp, ch
|
||
tjnz temp, #:printchar
|
||
call #cr
|
||
jmp #waitforchar
|
||
|
||
:bksp
|
||
sub col, #1 ' warning: no error-checking
|
||
jmp #waitforchar
|
||
|
||
:printchar
|
||
mov temp, #40
|
||
sub temp, col
|
||
tjnz temp, #:nocr
|
||
call #cr
|
||
:nocr
|
||
mov temp, col
|
||
shr temp, #2
|
||
add temp, #text+12*40/4
|
||
movs :get4chars, temp
|
||
movd :put4chars, temp
|
||
|
||
mov i, col
|
||
and i, #3
|
||
shl i, #3 ' col&3 => 0, 8, 16, 24
|
||
:get4chars mov temp, 0-0
|
||
ror temp, i
|
||
andn temp, #$ff
|
||
or temp, ch
|
||
rol temp, i
|
||
:put4chars mov 0-0, temp
|
||
|
||
add col, #1
|
||
|
||
|
||
jmp #waitforchar
|
||
|
||
cr
|
||
movs :move4chars, #text + 40 / 4
|
||
movd :move4chars, #text
|
||
|
||
mov i, #13 ' copy 13 lines up. Since we have an extra blank line at the bottom
|
||
' (see clearscreen) the last visible line is automatically cleared.
|
||
:copyline
|
||
mov j, #40/4
|
||
:move4chars mov 0-0, 0-0
|
||
add :move4chars, d0s0
|
||
djnz j, #:move4chars
|
||
jmpret taskptr,taskret
|
||
djnz i, #:copyline
|
||
|
||
mov col, #0
|
||
|
||
cr_ret ret
|
||
|
||
|
||
|
||
ping
|
||
mov temp, _basepin
|
||
shl temp, #8
|
||
wrlong temp, par
|
||
jmp #waitnoclear
|
||
|
||
enable
|
||
mov dira, saveDira
|
||
mov dirb, saveDirb
|
||
jmp #waitforchar
|
||
disable
|
||
mov dira, #0
|
||
mov dirb, #0
|
||
jmp #waitforchar
|
||
|
||
|
||
'
|
||
'
|
||
' Initialized data
|
||
'
|
||
x20202020 long $20202020
|
||
chset0 long $8000
|
||
m8 long 8_000_000
|
||
m128 long 128_000_000
|
||
d0 long 1 << 9 << 0
|
||
d6 long 1 << 9 << 6
|
||
d0s0 long 1 << 9 << 0 + 1 << 0
|
||
d0s1 long 1 << 9 << 0 + 1 << 1
|
||
interlace long 0
|
||
invisible long 1
|
||
visible long 2
|
||
phaseflip long $00000000
|
||
phasemask long $F0F0F0F0
|
||
line long $00060000
|
||
lineinc long $10000000
|
||
linerot long 0
|
||
pins0 long %11110000_01110000_00001111_00000111
|
||
pins1 long %11111111_11110111_01111111_01110111
|
||
sync_high1 long %0101010101010101010101_101010_0101
|
||
sync_high2 long %01010101010101010101010101010101 'used for black
|
||
sync_low1 long %1010101010101010101010101010_0101
|
||
sync_low2 long %01_101010101010101010101010101010
|
||
colortable
|
||
' long $07_0a_07_0a ' white on blue
|
||
' long $07_07_0a_0a
|
||
' long $bc_02_bc_02 ' green on black
|
||
' long $bc_bc_02_02
|
||
' long $05_02_05_02 ' white on black
|
||
' long $05_05_02_02
|
||
long $02_05_02_05 ' black on white
|
||
long $02_02_05_05
|
||
' long $8a_8c_8a_8c ' black on yellow
|
||
' long $8a_8a_8c_8c
|
||
|
||
|
||
'
|
||
'
|
||
' NTSC/PAL metrics tables
|
||
' ntsc pal
|
||
' ----------------------------------------------
|
||
wtab word lntsc - sntsc, lpal - spal 'hvis
|
||
word lntsc / 2 - sntsc, lpal / 2 - spal 'hrest
|
||
word lntsc / 2, lpal / 2 'hhalf
|
||
word 243, 286 'vvis
|
||
word 10, 18 'vinv
|
||
word 6, 5 'vrep
|
||
word $02_8A, $02_AA 'burst
|
||
wtabx
|
||
ltab long fntsc 'fcolor
|
||
long fpal
|
||
long sntsc >> 4 << 12 + sntsc 'sync_scale1
|
||
long spal >> 4 << 12 + spal
|
||
long 67 << 12 + lntsc / 2 - sntsc 'sync_scale2
|
||
long 79 << 12 + lpal / 2 - spal
|
||
long %0101_00000000_01_10101010101010_0101 'sync_normal
|
||
long %010101_00000000_01_101010101010_0101
|
||
ltabx
|
||
|
||
cmdPing long -1
|
||
cmdEnable long "E"<<8
|
||
cmdDisable long "D"<<8
|
||
_basepin long 0
|
||
'
|
||
'
|
||
' Parameter buffer
|
||
'
|
||
_enable long 1 'enable
|
||
_pins long 0 'pins
|
||
_mode long %10010 'mode
|
||
_screen long 0 'screen
|
||
_colors long 0 'colors
|
||
_ht long cols 'hc
|
||
_vt long rows 'vc
|
||
_hx long 4 'hx
|
||
_vx long 1 'vx
|
||
_ho long 0 'ho
|
||
_vo long 0 'vo
|
||
_broadcast long 0 'broadcast
|
||
_auralcog long 0 'auralcog
|
||
|
||
|
||
'
|
||
'
|
||
' Uninitialized data
|
||
'
|
||
i long 0
|
||
j long 0
|
||
col long 0
|
||
ch long 0
|
||
temp long 0
|
||
|
||
char long 0
|
||
chset long 0
|
||
chars4 long 0
|
||
pixels16 long 0
|
||
taskptr long 0 'tasks
|
||
taskret long 0
|
||
t1 long 0
|
||
t2 long 0
|
||
t3 long 0
|
||
m1 long 0
|
||
m2 long 0
|
||
|
||
x long 0 'display
|
||
y long 0
|
||
hf long 0
|
||
hb long 0
|
||
vf long 0
|
||
vb long 0
|
||
hx long 0
|
||
vx long 0
|
||
hc2x long 0
|
||
screen long 0
|
||
tile long 0
|
||
pixels long 0
|
||
lineadd long 0
|
||
|
||
hvis long 0 'loaded from word table
|
||
hrest long 0
|
||
hhalf long 0
|
||
vvis long 0
|
||
vinv long 0
|
||
vrep long 0
|
||
burst long 0
|
||
|
||
fcolor long 0 'loaded from long table
|
||
sync_scale1 long 0
|
||
sync_scale2 long 0
|
||
sync_normal long 0
|
||
|
||
saveDira long 0
|
||
saveDirb long 0
|
||
|
||
|
||
text ' Cog memory from this point on will be reclaimed as text buffer.
|
||
|
||
init
|
||
mov t1,_pins 'set video pins and directions
|
||
test t1,#$08 wc
|
||
if_nc mov t2,pins0
|
||
if_c mov t2,pins1
|
||
test t1,#$40 wc
|
||
shr t1,#1
|
||
shl t1,#3
|
||
shr t2,t1
|
||
movs vcfg,t2
|
||
shr t1,#6
|
||
movd vcfg,t1
|
||
shl t1,#3
|
||
and t2,#$FF
|
||
shl t2,t1
|
||
if_nc mov dira,t2
|
||
if_nc mov saveDira, t2
|
||
if_nc mov dirb,#0
|
||
if_nc mov saveDirb, #0
|
||
if_c mov dira,#0
|
||
if_c mov saveDira, #0
|
||
if_c mov dirb,t2 '+18
|
||
if_c mov saveDirb, t2
|
||
|
||
|
||
|
||
movs :rd,#wtab 'load ntsc/pal metrics from word table
|
||
movd :wr,#hvis
|
||
mov t1,#wtabx - wtab
|
||
test _mode,#%0001 wc
|
||
:rd mov t2,0
|
||
add :rd,#1
|
||
if_nc shl t2,#16
|
||
shr t2,#16
|
||
:wr mov 0,t2
|
||
add :wr,d0
|
||
djnz t1,#:rd '+54
|
||
|
||
if_nc movs :ltab,#ltab 'load ntsc/pal metrics from long table
|
||
if_c movs :ltab,#ltab+1
|
||
movd :ltab,#fcolor
|
||
mov t1,#(ltabx - ltab) >> 1
|
||
:ltab mov 0,0
|
||
add :ltab,d0s1
|
||
djnz t1,#:ltab '+17
|
||
|
||
rdlong t1,#0 'get CLKFREQ
|
||
shr t1,#1 'if CLKFREQ < 16MHz, cancel _broadcast
|
||
cmp t1,m8 wc
|
||
if_c mov _broadcast,#0
|
||
shr t1,#1 'if CLKFREQ < color frequency * 4, disable
|
||
' cmp t1,fcolor wc
|
||
' if_c jmp #disabled '+11
|
||
|
||
|
||
mov t1,fcolor 'set ctra pll to fcolor * 16
|
||
call #divide 'if ntsc, set vco to fcolor * 32 (114.5454 MHz)
|
||
test _mode,#%0001 wc 'if pal, set vco to fcolor * 16 (70.9379 MHz)
|
||
if_c movi ctra,#%00001_111 'select fcolor * 16 output (ntsc=/2, pal=/1)
|
||
if_nc movi ctra,#%00001_110
|
||
if_nc shl t2,#1
|
||
mov frqa,t2 '+147
|
||
|
||
mov t1,_broadcast 'set ctrb pll to _broadcast
|
||
mov t2,#0 'if 0, turn off ctrb
|
||
tjz t1,#:off
|
||
min t1,m8 'limit from 8MHz to 128MHz
|
||
max t1,m128
|
||
mov t2,#%00001_100 'adjust _broadcast to be within 4MHz-8MHz
|
||
:scale shr t1,#1 '(vco will be within 64MHz-128MHz)
|
||
cmp m8,t1 wc
|
||
if_c add t2,#%00000_001
|
||
if_c jmp #:scale
|
||
:off movi ctrb,t2
|
||
call #divide
|
||
mov frqb,t2 '+165
|
||
|
||
mov t1,#%10100_000 'set video configuration
|
||
test _pins,#$01 wc '(swap broadcast/baseband output bits?)
|
||
if_c or t1,#%01000_000
|
||
test _mode,#%1000 wc '(strip chroma from broadcast?)
|
||
if_nc or t1,#%00010_000
|
||
test _mode,#%0100 wc '(strip chroma from baseband?)
|
||
if_nc or t1,#%00001_000
|
||
and _auralcog,#%111 '(set aural cog)
|
||
or t1,_auralcog
|
||
movi vcfg,t1 '+10
|
||
|
||
mov hx,_hx 'compute horizontal metrics
|
||
shl hx,#8
|
||
or hx,_hx
|
||
shl hx,#4
|
||
|
||
mov hc2x,_ht
|
||
shl hc2x,#1
|
||
|
||
mov t1,_ht
|
||
mov t2,_hx
|
||
call #multiply
|
||
mov hf,hvis
|
||
sub hf,t1
|
||
shr hf,#1 wc
|
||
mov hb,_ho
|
||
addx hb,hf
|
||
sub hf,_ho '+52
|
||
|
||
mov t1,_vt 'compute vertical metrics
|
||
mov t2,_vx
|
||
call #multiply
|
||
test _mode,#%10000 wc 'consider tile size
|
||
muxc linerot,#1
|
||
mov lineadd,lineinc
|
||
if_c shr lineadd,#1
|
||
if_c shl t1,#1
|
||
test _mode,#%0010 wc 'consider interlace
|
||
if_c shr t1,#1
|
||
mov vf,vvis
|
||
sub vf,t1
|
||
shr vf,#1 wc
|
||
neg vb,_vo
|
||
addx vb,vf
|
||
add vf,_vo '+53
|
||
|
||
|
||
init_ret ret
|
||
|
||
'
|
||
'
|
||
' Divide t1/CLKFREQ to get frqa or frqb value into t2
|
||
'
|
||
divide rdlong m1,#0 'get CLKFREQ
|
||
|
||
mov m2,#32+1
|
||
:loop cmpsub t1,m1 wc
|
||
rcl t2,#1
|
||
shl t1,#1
|
||
djnz m2,#:loop
|
||
|
||
divide_ret ret '+140
|
||
'
|
||
'
|
||
' Multiply t1 * t2 * 16 (t1, t2 = bytes)
|
||
'
|
||
multiply shl t2,#8+4-1
|
||
|
||
mov m1,#8
|
||
:loop shr t1,#1 wc
|
||
if_c add t1,t2
|
||
djnz m1,#:loop
|
||
|
||
multiply_ret ret '+37
|
||
|
||
|
||
''
|
||
''___
|
||
''VAR 'TV parameters - 14 contiguous longs
|
||
''
|
||
'' long tv_status '0/1/2 = off/invisible/visible read-only
|
||
'' 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 write-only
|
||
''
|
||
''The preceding VAR section may be copied into your code.
|
||
''After setting variables, do start(@tv_status) to start driver.
|
||
''
|
||
''All parameters are reloaded each superframe, allowing you to make live
|
||
''changes. To minimize flicker, correlate changes with tv_status.
|
||
''
|
||
''Experimentation may be required to optimize some parameters.
|
||
''
|
||
''Parameter descriptions:
|
||
'' _________
|
||
'' tv_status
|
||
''
|
||
'' driver sets this to indicate status:
|
||
'' 0: driver disabled (tv_enable = 0 or CLKFREQ < requirement)
|
||
'' 1: currently outputting invisible sync data
|
||
'' 2: currently outputting visible screen data
|
||
'' _________
|
||
'' tv_enable
|
||
''
|
||
'' 0: disable (pins will be driven low, reduces power)
|
||
'' non-0: enable
|
||
'' _______
|
||
'' tv_pins
|
||
''
|
||
'' 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
|
||
'' -----------------------------------------------------------
|
||
'' active pins top nibble bottom nibble
|
||
''
|
||
'' the baseband signal nibble is arranged as:
|
||
'' bit 3: chroma signal for s-video (attach via 560-ohm resistor)
|
||
'' bits 2..0: baseband video (sum 270/560/1100-ohm resistors to form 75-ohm 1V signal)
|
||
''
|
||
'' the broadcast signal nibble is arranged as:
|
||
'' bit 3: aural subcarrier (sum 560-ohm resistor into network below)
|
||
'' bits 2..0: visual carrier (sum 270/560/1100-ohm resistors to form 75-ohm 1V signal)
|
||
'' _______
|
||
'' tv_mode
|
||
''
|
||
'' bit 4 selects between 16x16 and 16x32 pixel tiles:
|
||
'' 0: 16x16 pixel tiles (tileheight = 16)
|
||
'' 1: 16x32 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
|
||
'' _________
|
||
'' tv_screen
|
||
''
|
||
'' pointer to words which define screen contents (left-to-right, top-to-bottom)
|
||
'' number of words must be tv_ht * tv_vt
|
||
'' each word has two bitfields: a 6-bit colorset ptr and a 10-bit pixelgroup ptr
|
||
'' bits 15..10: select the colorset* for the associated pixel tile
|
||
'' bits 9..0: select the pixelgroup** address %ppppppppppcccc00 (p=address, c=0..15)
|
||
''
|
||
'' * colorsets are longs which each define four 8-bit colors
|
||
''
|
||
'' ** pixelgroups are <tileheight> longs which define (left-to-right, top-to-bottom) the 2-bit
|
||
'' (four color) pixels that make up a 16x16 or a 32x32 pixel tile
|
||
'' _________
|
||
'' tv_colors
|
||
''
|
||
'' pointer to longs which define colorsets
|
||
'' number of longs must be 1..64
|
||
'' each long has four 8-bit fields which define colors for 2-bit (four color) pixels
|
||
'' first long's bottom color is also used as the screen background color
|
||
'' 8-bit color fields are as follows:
|
||
'' bits 7..4: chroma data (0..15 = blue..green..red..)*
|
||
'' bit 3: controls chroma modulation (0=off, 1=on)
|
||
'' bits 2..0: 3-bit luminance level:
|
||
'' values 0..1: reserved for sync - don't use
|
||
'' values 2..7: valid luminance range, modulation adds/subtracts 1 (beware of 7)
|
||
'' value 0 may be modulated to produce a saturated color toggling between levels 1 and 7
|
||
''
|
||
'' * because of TV's limitations, it doesn't look good when chroma changes abruptly -
|
||
'' rather, use luminance - change chroma only against a black or white background for
|
||
'' best appearance
|
||
'' _____
|
||
'' tv_ht
|
||
''
|
||
'' horizontal number pixel tiles - must be at least 1
|
||
'' practical limit is 40 for NTSC, 50 for PAL
|
||
'' _____
|
||
'' tv_vt
|
||
''
|
||
'' vertical number of pixel tiles - must be at least 1
|
||
'' practical limit is 13 for NTSC, 15 for PAL (26/30 max for interlaced NTSC/PAL)
|
||
'' _____
|
||
'' tv_hx
|
||
''
|
||
'' horizontal tile expansion factor - must be at least 3 for NTSC, 4 for PAL
|
||
''
|
||
'' make sure 16 * tv_ht * tv_hx + ||tv_ho + 32 is less than the horizontal display ticks
|
||
'' _____
|
||
'' tv_vx
|
||
''
|
||
'' vertical tile expansion factor - must be at least 1
|
||
''
|
||
'' make sure <tileheight> * tv_vt * tv_vx + ||tv_vo + 1 is less than the display lines
|
||
'' _____
|
||
'' tv_ho
|
||
''
|
||
'' horizontal offset in ticks - pos/neg value (0 for centered image)
|
||
'' shifts the display right/left
|
||
'' _____
|
||
'' tv_vo
|
||
''
|
||
'' vertical offset in lines - pos/neg value (0 for centered image)
|
||
'' shifts the display up/down
|
||
'' ____________
|
||
'' tv_broadcast
|
||
''
|
||
'' broadcast frequency expressed in Hz (ie channel 2 is 55_250_000)
|
||
'' if 0, modulator is turned off - saves power
|
||
''
|
||
'' broadcasting requires CLKFREQ to be at least 16_000_000
|
||
'' while CLKFREQ is below 16_000_000, modulator will be turned off
|
||
'' ___________
|
||
'' tv_auralcog
|
||
''
|
||
'' selects cog to supply aural fm signal - 0..7
|
||
'' uses ctra pll output from selected cog
|
||
''
|
||
'' in NTSC, the offset frequency must be 4.5MHz and the max bandwidth +-25KHz
|
||
'' in PAL, the offset frequency and max bandwidth vary by PAL type
|
||
|
||
{{
|
||
|
||
+------------------------------------------------------------------------------------------------------------------------------+
|
||
<EFBFBD> TERMS OF USE: MIT License <20>
|
||
+------------------------------------------------------------------------------------------------------------------------------<2D>
|
||
<EFBFBD>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation <20>
|
||
<EFBFBD>files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, <20>
|
||
<EFBFBD>modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software<72>
|
||
<EFBFBD>is furnished to do so, subject to the following conditions: <20>
|
||
<EFBFBD> <20>
|
||
<EFBFBD>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.<2E>
|
||
<EFBFBD> <20>
|
||
<EFBFBD>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE <20>
|
||
<EFBFBD>WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR <20>
|
||
<EFBFBD>COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, <20>
|
||
<EFBFBD>ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. <20>
|
||
+------------------------------------------------------------------------------------------------------------------------------+
|
||
}} |