160x120 color for TV?
Dr_Acula
Posts: 5,484
I'm wondering if anyone has done a 160x120 color TV video driver?
This is pulling in a few threads and I think it has been asked before. We have
1) Kye's 160x120 VGA driver playing movies http://forums.parallax.com/showthread.php?127448-Play-movies-on-the-propeller&highlight=160x120
2) Rayman's movie player - which fills about 1/4 of the screen http://forums.parallax.com/showthread.php?116192
3) A discussion from Bill Henning http://forums.parallax.com/showthread.php?131397-Where-can-I-find-a-160x120-bitmap-4-color-TV-driver-I-could-not-find-one-in-OBEX
4) and another discussion from Bill Henning http://forums.parallax.com/showthread.php?116786-Bitmapped-NTSC-driver
Now, before Kye came out with the VGA driver, I was not sure this could be done. The code is deceptively simple but I still don't understand it. I'll get back to that in a sec.
1 byte per pixel seems to be a good resolution. It doesn't quite use all the data available, because in VGA mode only 6 of the 8 bits are being used. And for TV there are a number of unused byte values. But for simplicity sake, it makes sense to use this resolution and get 64 colors for VGA and a few more than that for TV.
Rayman's driver is extraordinary, in that he adds in interlaced sound as well. I downloaded the files from the link above, changed the SD card pins, changed the video mode from long %010_0101 to long %010_0000, put the movie file on the sd card and it ran straight out of the box.
But it does not appear to be full screen. The video is in the centre of the screen and I think it is only using 1/4 of the screen size.
My simple idea is to make the pixels twice as big in the x and y directions, and fill the screen. This should use the same amount of ram - ie 19200 bytes. On a 4.3" display I'm pretty sure the pixels will not be too blocky.
But I'm a bit lost with the relationship between palattes and pixels. Most code out there assumes a smaller palatte, eg 4 colors per tile. I'm not entirely sure that this should use tiles. The core of Kye's VGA driver seems to be this
Indeed, the entire pasm code of Kye's driver seems so simple compared with other video driver code. Here it is in its entirety.
Below is Rayman's video driver, which is putting video in the centre of the screen, and the rest of the screen is blue
Would it be possible to take Rayman's code and get it to fill the screen, using bigger pixels?
This is pulling in a few threads and I think it has been asked before. We have
1) Kye's 160x120 VGA driver playing movies http://forums.parallax.com/showthread.php?127448-Play-movies-on-the-propeller&highlight=160x120
2) Rayman's movie player - which fills about 1/4 of the screen http://forums.parallax.com/showthread.php?116192
3) A discussion from Bill Henning http://forums.parallax.com/showthread.php?131397-Where-can-I-find-a-160x120-bitmap-4-color-TV-driver-I-could-not-find-one-in-OBEX
4) and another discussion from Bill Henning http://forums.parallax.com/showthread.php?116786-Bitmapped-NTSC-driver
Now, before Kye came out with the VGA driver, I was not sure this could be done. The code is deceptively simple but I still don't understand it. I'll get back to that in a sec.
1 byte per pixel seems to be a good resolution. It doesn't quite use all the data available, because in VGA mode only 6 of the 8 bits are being used. And for TV there are a number of unused byte values. But for simplicity sake, it makes sense to use this resolution and get 64 colors for VGA and a few more than that for TV.
Rayman's driver is extraordinary, in that he adds in interlaced sound as well. I downloaded the files from the link above, changed the SD card pins, changed the video mode from long %010_0101 to long %010_0000, put the movie file on the sd card and it ran straight out of the box.
But it does not appear to be full screen. The video is in the centre of the screen and I think it is only using 1/4 of the screen size.
My simple idea is to make the pixels twice as big in the x and y directions, and fill the screen. This should use the same amount of ram - ie 19200 bytes. On a 4.3" display I'm pretty sure the pixels will not be too blocky.
But I'm a bit lost with the relationship between palattes and pixels. Most code out there assumes a smaller palatte, eg 4 colors per tile. I'm not entirely sure that this should use tiles. The core of Kye's VGA driver seems to be this
' //////////////////////Visible Video////////////////////////////////////////////////////////////////////////////////////////// videoLoop rdlong buffer, displayCounter ' Download new pixels. add displayCounter, #4 ' or buffer, HVSyncColors ' Update display scanline. waitvid buffer, #%%3210 ' djnz counter, #videoLoop ' Repeat.
Indeed, the entire pasm code of Kye's driver seems so simple compared with other video driver code. Here it is in its entirety.
DAT ' ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ' PIX Driver ' ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// org 0 ' //////////////////////Initialization///////////////////////////////////////////////////////////////////////////////////////// initialization mov vcfg, videoState ' Setup video hardware. mov frqa, frequencyState ' movi ctra, #%0_00001_101 ' ' ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ' Active Video ' ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// loop mov displayCounter, par ' Set/Reset tiles fill counter. mov tilesCounter, #120 ' tilesDisplay mov tileCounter, #4 ' Set/Reset tile fill counter. tileDisplay mov vscl, visibleScale ' Set/Reset the video scale. mov counter, #40 ' ' //////////////////////Visible Video////////////////////////////////////////////////////////////////////////////////////////// videoLoop rdlong buffer, displayCounter ' Download new pixels. add displayCounter, #4 ' or buffer, HVSyncColors ' Update display scanline. waitvid buffer, #%%3210 ' djnz counter, #videoLoop ' Repeat. ' //////////////////////Invisible Video//////////////////////////////////////////////////////////////////////////////////////// mov vscl, invisibleScale ' Set/Reset the video scale. waitvid HSyncColors, syncPixels ' Horizontal Sync. ' //////////////////////Repeat///////////////////////////////////////////////////////////////////////////////////////////////// sub displayCounter, #160 ' Repeat. djnz tileCounter, #tileDisplay ' add displayCounter, #160 ' Repeat. djnz tilesCounter, #tilesDisplay ' ' ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ' Inactive Video ' ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// add refreshCounter, #1 ' Update sync indicator. wrbyte refreshCounter, syncIndicatorAddress ' ' //////////////////////Front Porch//////////////////////////////////////////////////////////////////////////////////////////// mov counter, #11 ' Set loop counter. frontPorch mov vscl, blankPixels ' Invisible lines. waitvid HSyncColors, #0 ' mov vscl, invisibleScale ' Horizontal Sync. waitvid HSyncColors, syncPixels ' djnz counter, #frontPorch ' Repeat # times. ' //////////////////////Vertical Sync////////////////////////////////////////////////////////////////////////////////////////// mov counter, #(2 + 2) ' Set loop counter. verticalSync mov vscl, blankPixels ' Invisible lines. waitvid VSyncColors, #0 ' mov vscl, invisibleScale ' Vertical Sync. waitvid VSyncColors, syncPixels ' djnz counter, #verticalSync ' Repeat # times. ' //////////////////////Back Porch///////////////////////////////////////////////////////////////////////////////////////////// mov counter, #31 ' Set loop counter. backPorch mov vscl, blankPixels ' Invisible lines. waitvid HSyncColors, #0 ' mov vscl, invisibleScale ' Horizontal Sync. waitvid HSyncColors, syncPixels ' djnz counter, #backPorch ' Repeat # times. ' //////////////////////Update Display Settings//////////////////////////////////////////////////////////////////////////////// rdbyte buffer, displayIndicatorAddress wz ' Update display settings. muxnz dira, directionState ' ' //////////////////////Loop/////////////////////////////////////////////////////////////////////////////////////////////////// jmp #loop ' Loop. ' ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ' Data ' ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// invisibleScale long (16 << 12) + 160 ' Scaling for inactive video. visibleScale long (4 << 12) + 16 ' Scaling for active video. blankPixels long 640 ' Blank scanline pixel length. syncPixels long $00_00_3F_FC ' F-porch, h-sync, and b-porch. HSyncColors long $01_03_01_03 ' Horizontal sync color mask. VSyncColors long $00_02_00_02 ' Vertical sync color mask. HVSyncColors long $03_03_03_03 ' Horizontal and vertical sync colors. ' //////////////////////Configuration Settings///////////////////////////////////////////////////////////////////////////////// directionState long 0 videoState long 0 frequencyState long 0 ' //////////////////////Addresses////////////////////////////////////////////////////////////////////////////////////////////// displayIndicatorAddress long 0 syncIndicatorAddress long 0 ' //////////////////////Run Time Variables///////////////////////////////////////////////////////////////////////////////////// counter res 1 buffer res 1 tileCounter res 1 tilesCounter res 1 refreshCounter res 1 displayCounter res 1 ' ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// fit 496 DAT ' //////////////////////Variable Arrary//////////////////////////////////////////////////////////////////////////////////////// displayBuffer long 0[(160 * 120) / 4] ' Display buffer. displayIndicator byte 1 ' Video output control. syncIndicator byte 0 ' Video update control. cogNumber byte 0 ' Cog ID.
Below is Rayman's video driver, which is putting video in the centre of the screen, and the rest of the screen is blue
DAT '******************************* '* Assembly language TV driver * '******************************* org ' ' ' Entry ' entry mov taskptr,#tasks 'reset tasks mov x,#10 'perform task sections initially :init jmpret taskret,taskptr djnz x,#:init ' DAT ' Superfield ' superfield mov taskptr,#tasks 'reset tasks test _mode,#%0001 wc 'if ntsc, set phaseflip if_nc mov phaseflip,phasemask test _mode,#%0010 wz 'get interlace into nz ' ' DAT 'Get bitmap info from color #64 '******************************************************************************************** 'Get bmp Address mov bmpAdd,colortable+63 mov bmpCols,bmpAdd shr bmpCols,#24 mov bmpRows,bmpAdd shr bmpRows,#16 and bmpRows,#$FF mov bmpWaits,bmpCols shr bmpWaits,#2 mov PadLeft,ScreenCols sub PadLeft,bmpCols shr PadLeft,#2 mov PadRight,PadLeft shr PadRight,#1 sub PadLeft,PadRight '******************************************************************************************** DAT ' 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 DAT 'Point to start of bitmap '******************************************************************************************** 'reset bmp color pointer mov PixAdd,bmpadd sub PixAdd,bmpCols 'Move to start of line add PixAdd,#4 mov LinesLeft,screenRows '******************************************************************************************** DAT mov screen,_screen 'point to first tile (upper-leftmost) mov y,_vt 'set vertical tiles :line mov vx,_vx 'set vertical expand :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 DAT 'Decide between bitmap or tile '*************************************************************************** 'tile or bmp cmp LinesLeft,BmpRows wz,wc if_be jmp #:BmpLine '*************************************************************************** DAT :DoTile mov vscl,hx 'set horizontal expand :tile rdword tile,screen 'read tile or tile,line 'set pointer bits into tile rol tile,#6 'read tile pixels rdlong pixels,tile '(2 instructions between reads) shr tile,#10+6 'set tile colors movs :color,tile add screen,#2 'point to next tile mov tile,phaseflip :color xor tile,colortable waitvid tile,pixels 'pass colors and pixels to video djnz x,#:tile 'another tile? sub screen,hc2x 'repoint to first tile in same line mov vscl,hf 'do visible front porch pixels mov tile,phaseflip xor tile,colortable waitvid tile,#0 DAT 'Do a line of BMP image '*************************************************************************** jmp #:DoneLine :BmpLine mov vscl,hx_test 'set horizontal expand cmp PadLeft,#0 wz,wc if_e jmp #:BmpPixels mov x,PadLeft 'do some background pixels 'pass colors and pixels to video :LeftPad mov tile,phaseflip xor tile,colortable waitvid tile,zero djnz x,#:LeftPad :BmpPixels 'Do bitmap pixels mov x,bmpWaits :GetColor1 rdlong PixRead,PixAdd add PixAdd,#4 mov tile,phaseflip xor tile,PixRead waitvid tile,#%%3210 djnz x,#:GetColor1 'another tile? cmp PadRight,#0 wz,wc if_e jmp #:RightPadDone mov x,PadRight 'do some more background pixels 'pass colors and pixels to video :RightPad mov tile,phaseflip xor tile,colortable waitvid tile,zero djnz x,#:RightPad :RightPadDone sub screen,hc2x 'repoint to first tile in same line mov vscl,hf 'do visible front porch pixels mov tile,phaseflip xor tile,colortable waitvid tile,#0 'Line is done! :BmpLineDone 'reset bmp color pointer sub PixAdd,bmpCols sub PixAdd,bmpCols :DoneLine sub LinesLeft,#1 '************************************************************************************************ DAT :skip djnz vx,#:vert 'vertical expand? ror line,linerot 'set next line add line,lineadd wc rol line,linerot if_nc jmp #:line add screen,hc2x 'point to first tile in next line 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_nz 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 DAT 'Variables for doing bitmap '*************************************************************************************** 'NOTE: The variables that are zero here (except "zero") can be changed to RES 1 and moved to end to save a few bytes... bmpadd long 0 'address of bmp PixRead long 0 PixAdd long 0 hx_test long 10<<12+40 zero long 0 bmpRows long 0 bmpCols long 0 bmpWaits long 0 ScreenRows long y_tiles*16'192 ScreenCols long x_tiles*16'256 PadLeft long 0 PadRight long 0 LinesLeft long 0 '*************************************************************************************** DAT ' ' ' 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,phaseflip xor tile,burst waitvid tile,sync_normal mov vscl,hvis 'setup in case blank line mov tile,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 mov t1,par 'load parameters movd :par,#_enable '(skip _status) mov t2,#paramcount - 1 :load add t1,#4 :par rdlong 0,t1 add :par,d0 djnz t2,#:load '+119 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 dirb,#0 if_c mov dira,#0 if_c mov dirb,t2 '+18 tjz _enable,#disabled '+2, disabled? jmpret taskptr,taskret '+1=140, break and return later 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 jmpret taskptr,taskret '+1=83, break and return later 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 jmpret taskptr,taskret '+1=148, break and return later 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 jmpret taskptr,taskret '+1=166, break and return later 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 xor _mode,#%0010 '+1, flip interlace bit for display :colors jmpret taskptr,taskret '+1=117/160, break and return later mov t1,#13 'load next 13 colors into colortable :colorloop mov t2,:colorreg '5 times = 65 (all 64 colors loaded) shr t2,#9-2 and t2,#$FC add t2,_colors :colorreg rdlong colortable,t2 add :colorreg,d0 andn :colorreg,d6 djnz t1,#:colorloop '+158 jmp #:colors '+1, keep loading colors ' ' ' 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 ' ' ' Disabled - reset status, nap ~4ms, try again ' disabled mov ctra,#0 'reset ctra mov ctrb,#0 'reset ctrb mov vcfg,#0 'reset video wrlong outa,par 'set status to disabled rdlong t1,#0 'get CLKFREQ shr t1,#8 'nap for ~4ms min t1,#3 add t1,cnt waitcnt t1,#0 jmp #entry 'reload parameters ' ' ' Initialized data ' m8 long 8_000_000 m128 long 128_000_000 d0 long 1 << 9 << 0 d6 long 1 << 9 << 6 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 ' ' ' 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 ' ' ' Uninitialized data ' taskptr res 1 'tasks taskret res 1 t1 res 1 t2 res 1 m1 res 1 m2 res 1 x res 1 'display y res 1 hf res 1 hb res 1 vf res 1 vb res 1 hx res 1 vx res 1 hc2x res 1 screen res 1 tile res 1 pixels res 1 lineadd res 1 hvis res 1 'loaded from word table hrest res 1 hhalf res 1 vvis res 1 vinv res 1 vrep res 1 burst res 1 fcolor res 1 'loaded from long table sync_scale1 res 1 sync_scale2 res 1 sync_normal res 1 ' ' ' Parameter buffer ' _enable res 1 '0/non-0 read-only _pins res 1 '%pppmmmm read-only _mode res 1 '%tccip read-only _screen res 1 '@word read-only _colors res 1 '@long read-only _ht res 1 '1+ read-only _vt res 1 '1+ read-only _hx res 1 '4+ read-only _vx res 1 '1+ read-only _ho res 1 '0+- read-only _vo res 1 '0+- read-only _broadcast res 1 '0+ read-only _auralcog res 1 '0-7 read-only fit colortable 'fit underneath colortable ($180-$1BF) '' ''___ ''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
Would it be possible to take Rayman's code and get it to fill the screen, using bigger pixels?
Comments
But I thought there was a more recent thread too...
Edit: I think this is the more recent thread I was thinking of, but uses two props
It uses the standard Parallax TV and Graphic drivers modified for 8bit TV. you get roughly 16 colors and 8 shades on the TV
I can't seem to find where it came from though, I could zip it up for you if you like,
but.... do you want a TV driver or a VGA driver, I think it would not be too difficult to change that driver to do a 2bit per color VGA driver!
Perry
I need to reread that thread, because I get the impression with timing that VGA is harder than TV, so if VGA is working, TV must be possible too.
Tiny 4x8 tiles. I modified the tvproperties file to this so it runs on the dracblade (pin group 16)
And it is displaying mario in full color. Plus some fonts, plus some moving tiles.
I am not sure how this is working - tiles vs a full bitmapped 19200 byte array. I think it might be more than 160x120 too. Maybe 256x240?
Tiles vs bitmapped may not be such an issue if screens can be built on the fly in software (eg with XMM C), and thus free up most/all the hub ram for tile buffers.
It is a gorgeous loking picture. At 60cm the pixels are not really visible even with my glasses on. I'd love to get a movie version going...
Hmm - 256x240 is more than hub ram, so the "trick" must be that mario is mostly white background. May need to come back to 160x120 for movies. Though could go higher for things like a GUI, since many tiles will be white or gray background.
be patient after loading it seems to take 4 seconds before starting to display.
Perry
My drivers use Chip's TV as a base so they all work in PAL or NTSC too.
Baggers - I'd like to start with 160x120 with one byte per pixel - ie replicate Kye's VGA driver but on a small portable TV rather than a big VGA. Is Fat Pixel at that resolution - and have you got a link to the code?
I've thinking about that 8bx_Graphics driver, I bet it would work on Kye's VGA driver, by changing the spin color code. There is a CLUT version in the archives I have.
I don't have Prop VGA hardware to test this with, but you could have same software interface on VGA or TV
Perry
The answers are almost always: Yes all you have to do is...
You can yuse ... and modify ...
Why not just ...
Since the question of a 160x120 color driver for NTSC has been asked so many times, why does not some one that has the time to do so just look at all the existing answers that work and implement a basic 160x120 color NTSC driver.
I haven't seen anything that does what Kye's VGA driver does. I might see if I can work out how his video driver works. TV and VGA must be similar - on some movies playing on the VGA driver, the TV occasionally displays the same picture in black and white. So there must be some signals common to both on pins 16-18.
You see to have very little knowledge about VGA/TV differences the are quite a bit different.
VGA has five outputs on individual pins Red,Green,Blue, Horz sync and Vert sync
TV multiplexes color,luminance,horz sync and vert sync on to one pin.
Changinf the 8bc_Graphics diriver to 160x120 is trivial for me. THe problems is I don't know how you interface to the VGA driver,
If you use Kye's code only it should be easy to add those functions to the 8bc_TV driver and you would not use the graphics software interface. You should end up with a TV driver exactly like Kye's VGA driver but with only 16 colors and 8 shades.
I don't think it should look to bad.
Perry
My understanding is that there is a palatte of colors for TV which is somewhere between 64 and 100 colors - I'm not sure of the exact number but the Obex palatte demo shows them all - a range of colors in various saturations, plus a 5 gray scale, plus some supersaturated colors.
There is so much here that almost works but not quite. Kye and others have shown you can take byte values, one byte per pixel, and send them out using the waitvid command.
Rayman has shown you can have a 160x120 full color display on a TV screen but it is only occupying 1/4 of the screen.
So what I am looking for is Rayman's display driver, but with each pixel 2x bigger in the x and y direction so it fills the screen. I think that is just a matter of altering the time each color is displayed - display for twice as long, and display the next line the same.
But Rayman's driver is a little difficult to understand because it has both a tile driver and a bitmap driver in the pasm code. I need to study it some more.
These are the colors you are speaking of and that the 8b_Color driver uses. http://propeller.wikispaces.com/Colors
I believe propuser "Ale" runs the site but it is hard to tell.
I've tried some experiments with 160x120 and the 8bc_Color driver, it's proven to be more difficult than I thought. I seems to need 160x128 to work near to the resolution you desire. but makes a small display in the middle of the screen.
I am assuming you use plotPixel(colorl, xPixel, yPixel)
displayColor(redAmount, greenAmount, blueAmount)
and plotBox(color, xPixelStart, yPixelStart, xPixelEnd, yPixelEnd)
These are what I mean by the software interface that you use.
Perry
P.S.
I have been musing about trying to change the 1pin GreyTV driver to color.
it would have 8colors and 32 shades
No 160x120 is not set in stone. I think that worked out best on VGA as it divided into 640x480. But if a TV fits better into 512 lines or 256 or 128 that would be a better number.
The plotpixel, displaycolor are not 100% necessary - the main thing is the pasm driver. For converting video to pictures I'll probably do the conversion on a PC rather than on the prop as it will be faster. For testing, fill a big array with the standard hues/color bytes and repeat until the array is full?
$19, $1a, $1b, $1c, $1d, $1e, $98, $af 15 Hues
$29, $2a, $2b, $2c, $2d, $2e, $a8, $bf
$39, $3a, $3b, $3c, $3d, $3e, $b8, $cf
$49, $4a, $4b, $4c, $4d, $4e, $c8, $df
$59, $5a, $5b, $5c, $5d, $5e, $d8, $ef High saturation colors, placed
$69, $6a, $6b, $6c, $6d, $6e, $e8, $ff in table by closest hue match.
$79, $7a, $7b, $7c, $7d, $7e, $f8, $0f
$89, $8a, $8b, $8c, $8d, $8e, $08, $1f Hues are presented in this table
$99, $9a, $9b, $9c, $9d, $9e, $18, $2f vertically, in sequence as shown
$a9, $aa, $ab, $ac, $ad, $ae, $28, $3f in screenie below.
$b9, $ba, $bb, $bc, $bd, $be, $38, $4f
$c9, $ca, $cb, $cc, $cd, $ce, $48, $5f Start with intensity on left, and
$d9, $da, $db, $dc, $dd, $de, $58, $6f work to the right, starting at
$e9, $ea, $eb, $ec, $ed, $ee, $68, $7f top of table.
$f9, $fa, $fb, $fc, $fd, $fe, $78, $8f
It's pretty rough but here's what I have now.
P.S.
OOPs! sorry I just tried that code on a color TV, there seems to be little if any color
my bad !!!!
The previous version used the 8bc_Color code. Limitations on the x resolution are because the capture is done by the propeller sigma delta video ADC. I could update the Amazing video code with keyboard control instead of InfraRED.
Perry
P.S.
Just tried the code to with the 8bc_TV instead of Grey_TV. It will play my video files with false color because there are 8bits in the video. A few problems, mainly the 8bc_TV does not like colors below 2 (they are used for sync signals).
You could almost use this driver as is, all you would need is a utility to change some video to conform to the 8bc_TV limitations.
I have just got home and downloaded your code on the previous page and it is a very nice demo.
I think this is a tile demo, and looking at your code, I think the tiles are 16x16 and you have 8 tiles across and 6 down.
I think the issue here is the number of colors per tile. Can you have all colors per tile, or is the number of colors limited?
Or looking at it from Kye's driver's point of view, instead of tiles 16x16, you have tiles 1x1, and you have 1 byte per tile.
Or maybe to put it another way, how would I display a bitmap filling the entire screen of, say, a photograph?
I think you get close to this with your last pub
where I think that is 16x16 = 256 wide and 6x16 = 96 high. That makes 24576 bytes for the full screen buffer.
I'm thinking of something more with a ratio of 4:3, with roughly the same number of bytes (or small spin demos we can use most of hub ram for video buffer, and for C programs in external memory AND for pasm programs that are running purely from cogs (like sphinx), virtually all the hub ram is free.
I wonder if 10 tiles wide and 8 high would work? That is 160x128, a ratio of 1.25 (4/3 is 1.33) and 20480 bytes for the screen buffer. Or 11 tiles wide and 8 high, which gives a ratio of 1.375 and 22528 bytes for the buffer.
But I think the problem is still the number of colors per tile. Right at the end of Perry's code is this
and it is drawing a propeller with (I think) 5 colors, but it is doing this by drawing a 4 color propeller, then a second one on top of the first with different colors.
This is different to Kye's 'full color' driver, ie every pixel can be any color you like.
I hope I am explaining this right.
(goes off to search for the fractal thread)
http://forums.parallax.com/showthread.php?126429-RIP-Benoit-Mandelbrot-Propeller-demo-attached...
And, Eric did a pretty great NTSC driver that offers a great set of colors, more than the Parallax reference drivers do, at the resolutions you mention. It's really worth a look, because it's the best TV color space we have. It runs at 160xvarious resolutions.
http://forums.parallax.com/entry.php?60-NTSC-4x2
I captured the default image, which can be found here: http://forums.parallax.com/entry.php?88-Attachment-Bucket
Also in that post, is a variation of the low resolution driver linked above. 160x192 color for TV NTSC. Looking at that one, will show you what can and needs to change if you want different resolutions.
My code will do resolutions other than 160. 256, 320, 128, horizontal and various vertical are possible. Usually, it's just one scan line high, or two though, for 192, or 96. No big deal to add 8 lines and get 100 or 200.
All NTSC only though. Sorry about that.
*awaits eagerly*
To change this, you need to look at the Propeller data sheet, for the bit values, then edit the values you find in the code above.
You also need to edit the pin mask, down at the bottom:
That line sets the TV pins in use to output.
Sorry it isn't cleaner... early stuff. I'm not where I have a prop. I will go look at the data sheet later if you have trouble though....
I think I am a bit muddled with which version. This one http://forums.parallax.com/showthread.php?94975-High-color-TV.bitmap-driver-demo.&highlight=potatohead+fractal
Or something more recent? I found the pictures in the mandelbrot thread but no code?
Getting some garbage on the screen changing #3 to #2
movd VCFG, #2 ' VCFG'D = pingroup (grp. 3 i.e. pins 24-31)
and 24 to 16
'tvport_mask long %0000_0111<<24
tvport_mask long %0000_0111<<16
but not quite there. brb
FWIW this is Perry's code:
basepin = 16 ' change this to any pin
then
tv_pins := (basepin & $38) << 1 | (basepin & 4 == 4) & %0101
which is then passed as the third value in this group
and which I worked out gives a value of long %010_0000 'pins
Not sure if this helps with your code?
At that early time, we had a discussion of how many colors? That particular thread was one that I demonstrated how to exploit the NTSC color signal for a lot of colors! Basically, you put two pixels worth of color into one NTSC color cycle. NTSC color cycles at 160 pixels in the default active screen area. Running the high color driver at 320 pixels, puts two sets of color info into one color cycle, mixing the two together, which produces a lot of colors. Problem is HUB RAM. That demo takes 30K at 320x96. So it was just a curio, and something I did to just get used to the Propeller.
Eric's code that I linked refines that technique for a nicer color set. His setup approach is different though.
There are not a lot of differences between the few versions of that code out there. Here's the version used in the fractal demo: http://forums.parallax.com/showthread.php?126429-RIP-Benoit-Mandelbrot-Propeller-demo-attached...&p=948655&viewfull=1#post948655
It's got a mostly black and white capture, so it's easy to miss.
If you have other TV drivers running on your setup, go and look at the VCFG values, and the pin mask values OUTA. Match up the bit fields, then modify this code with those values. At the PASM level, it's all the same, with the differences being how the values are established. Later on, I moved to just one constant value for VCFG. All the TV drivers vary in how they do this, and I find it's easiest to just take working code for a given board and note those bit values, and then look back at the data sheet to see what they mean. Once that's done, modifying various TV drivers can be easier, as one can just go right to the register, put the long in there, and be done with it, or work backward through whatever setup method was used.
For any TV driver, you need to know the value put into the counter, clock, VCFG, and the pin mask. I would go farther and test for you, but I'm not where I can get to my PPDB and setup your pins to test...
I think I've done this work already. OBC wanted one for protoboard for a movie player. Let me see if I can find that.
We need a tutorial on this. There are too ($&%#(*$(*$#%@#$% many TV driver setup methodologies!
The colors available are the same as the URL I linked to.
It looks like a tile driver because the author wanted it to function like the Parallax TV and Graphics drivers.
There is 1 byte per pixel so you can get a different color per pixel
sorry about the confusion re: statements with pix and pixcolor that's left over from a demo I modified, should have been deleted.
but you still need to understand the fundamental difference between VGA and TV, TV has color and luminance, VGA has 3 separate colors each with it's own values.
you will need some kind of CLUT to translate from VGA to TV standards.
it seems that the 8bc_TV will not do 160 wide without making the pixels shorter and therefore truncating the visible x display.
Perry