I was also able to verify that the problem was the color combinations on my C64 monitor, I changes 1 line of code to guarantee no sync colors were used listed below:
Yes, I've noticed that if I alter the colors a bit that the color smearing effect can be minimized.
using: params(3) := $000CeFa brings it down to just M's and W's for the most part.
@potatohead: Did I understand that you were going to adjust params to be able to be called on the fly to
allow for changes in the color at any time? Or have I just not gotten far enough in my understanding yet?
(Finally figured out the bits to get this far, please add to documentation.) Still trying to digest all the info
you PM'ed me. [noparse]:)[/noparse]
Don't suppose that someone has created an index of colors?
Oldbitcollector said...
Don't suppose that someone has created an index of colors?
Yes, sort of. Start with this in char_mode_08_TV.spin ...
' ===== ADD
CON
RGB_BLACK = $02
RGB_GREY = $03
RGB_WHITE = $06
RGB_BRIGHT_WHITE = $07
RGB_CYAN = $3D
RGB_LIGHT_CYAN = $3E
RGB_LIGHT_GREEN = $5E
RGB_LIGHT_YELLOW = $8E
RGB_LIGHT_RED = $CE
RGB_LIGHT_MAGENTA = $FE
RGB_RED = $BC
RGB_YELLOW = $8D
RGB_GREEN = $5C
RGB_BLUE = $1C
RGB_MAGENTA = $FC
RGB_LIGHT_BLUE = $1E
' ===== ALTER CODE ...
:draw_pixels rdbyte B, A 'get a character from screen memory (A)
shl B, #3 'multiply by 8, for char offset
add B, fontsum 'add current scanline offset
rdbyte C, B 'read actual font pixels into (C)
mov r0,#CALC_bytes_per_line ' <=== NEW
sub r0,A
and r0,#$F
add r0,#PALETTE
movd :Output,r0
nop
:Output waitvid colors, C 'draw them to screen
add A, #1 'point to next set of chars
djnz r1, #:draw_pixels 'line done?
jmp #end_of_flag_line
' ===== ADD AT END OF DRIVER
PALETTE long RGB_WHITE << 8 | RGB_BLACK ' 0
long RGB_BLUE << 8 | RGB_BLACK ' 1
long RGB_GREEN << 8 | RGB_BLACK ' 2
long RGB_CYAN << 8 | RGB_BLACK ' 3
long RGB_RED << 8 | RGB_BLACK ' 4
long RGB_MAGENTA << 8 | RGB_BLACK ' 5
long RGB_YELLOW << 8 | RGB_BLACK ' 6
long RGB_BRIGHT_WHITE << 8 | RGB_BLACK ' 7
long RGB_GREY << 8 | RGB_BLACK ' 8
long RGB_LIGHT_BLUE << 8 | RGB_BLACK ' 9
long RGB_LIGHT_GREEN << 8 | RGB_BLACK ' 10
long RGB_LIGHT_CYAN << 8 | RGB_BLACK ' 11
long RGB_LIGHT_RED << 8 | RGB_BLACK ' 12
long RGB_LIGHT_MAGENTA << 8 | RGB_BLACK ' 13
long RGB_LIGHT_YELLOW << 8 | RGB_BLACK ' 14
long RGB_WHITE << 8 | RGB_RED ' 15
That will alternate every character column colour.
To have an array of colours per char which is what I was after you'll need to pass a pointer to the array in and update the :darw_pixels routine. My code is so different now to the original driver that posting my code to do that will not help you, and I've not implemented that part yet.
@hippy: Wow.. I've been picking through this the 'hunt & spin' way.
@Wes: Changing the divisor doesn't seem to help very much on my 1702 monitor
I've been discovering color combinations that work and keeping track of them.
Not sure what index + 2 is doing, altering it has no effect.
repeat index from 0 to 4096 step 4
c := c + 1
'c := c & %01111111
displayb[noparse][[/noparse]index] := $02 'background
'' 01 = BLACK 02 = BLACK 03 = DARK GREY 04 = PALE WHITE 06 = WHITE
'' 07 = BRIGHT WHITE 08 = DARK ORANGE 09 = DARK PURPLE 0a = PURPLE
'' 0b = BLUE 0c = LIGHT BLUE 0d = SKY BLUE 0e = BRIGHT LIGHT BLUE
'' 0f = BROWN 49 = DARK RED 5c = ORANGE 9c = GREEN cd = CYAN
displayb[noparse][[/noparse]index + 1] := $06 ' text color
displayb[noparse][[/noparse]index + 2] := $00
displayb[noparse][[/noparse]index + 3] := $1f 'character
Pleasantly, the smearing effect appears to be GONE in 16 bit mode...
May have spoke too soon, but it does appear to be lessened.
I thought I had pasted a CLUT (color lookup table) into the quickie demo program. Just checked and saw it isn't there. I've got a class to teach this friday --it's a new one, so I'm prepping like a mad dog. Won't have any real Propeller time until this weekend. Was sick, this last one!
The assembly language driver does not do a color lookup. Takes too long --at least that's the case at the moment. I've some ideas on how to address that, but it's gonna be a rewrite essentially. I think there is time during the sync, to grab a scanline full of chars. If so, maybe there will be time to do color mapping in the driver itself.
So, one must handle colors properly in their code that starts up the driver.
Additionally, so many good things have happened! Guess it's gonna have to be put together in a better package. Hippy's reverse code is a great piece. I was just using OpenOffice to do this. That means a build_font_table procedure, which has been done. Oldbitcollector has done an ASCII sort, which is largely a cut 'n paste, but for Hippy changing the colors to be run-time. That's not a tough one either, but will have to wait, on my part. The port of TV-Text is awesome too. All combined make for a totally different looking release!
Coupla things about that table. The intent was to map the colors in an easy to grok fashion. So, lower three bits (0-7) are intensity, with the highest Propeller intensity duplicated a few times. That's the $07 repeated.
The colors follow, hue by hue, using the upper bits to specify hue. That leaves room for only 15 hues, so one of the blues is not included. Those numbers are included below the CLUT, and can be traded for another hue, if desired.
For each hue, the very darkest one might be a problem, as will the very brightest ones. All of my TV's displayed these, so I thought it was good. If that's not the case, that table can be cut down to limit intensities to the safe 5, which are 02 - 06.
I included all the colors possible, that had a good chance of displaying correctly, should somebody want to push it. A more conservative (and likely safer table) would eliminate the low intensity hues, along with the highest intensity ones.
With the table in SPIN, one can use a simple color index, 0-127, to pick the colors and assign them with @@clut, to point to the table start.
That table applies to assembly code where one just blasts the screen memory bits to a waitvid, instead of operating on them. I've written the bitmap code and this character code the same way, so the same table can be used. The high-color bitmap program shows use of the table.
Wes has it spot on for the artifacting (color smearing). That's a big part of why the Commodore and Atari fonts almost never have single pixels standing alone. This driver uses fixed color timing on every scanline. That puts effective resolution at 160 pixels, which is half that required for a 40 char display. Packing the pixels together keeps artifacts to a minimum. White on blue is one of the very best choices, keeping that in mind.
One can really cut down on this artifacting by using the brightest blue, on dark blue. That syncs up all the color info more or less perfectly, keeping artifacts to an absolute minimum. That really applies to most any of the hues. Blue seems to be good on the eyes. I suspect this is because we have about a third of the blue receptors that we do red and green! BTW: that aspect of our physiology is used in video compression schemes. Reducing the detail level of the blue component results in almost no significant perception of image depredation! This is also why we have such a hard time with higher levels of detail being drawn in blue.
Best color combos are:
Text and background same hue, different intensity.
Text white or black, background low intensity hue.
From there it downgrades..
Text white, background black, or inverse.
Text one color, background another. (worst case)
Since Hippy is looking at PAL, I'll go back to work on getting this up and running with interlaced color. That will significantly improve readability. Artifacts will alternate every other scanline and frame, and will cancel out, leaving 320 pixels of color resolution. Thta 160 pixel limitation is the dots surrounding each colored char, most easily seen on contrasting hues.
Finally, I suspect some of the smearing comes from the TV filter, and off color combinations. (text and background different hue, or black.) If you cut the saturation down, contrast up, sharpness up (if your tube has that one), those effects will be sharply diminished. Used to run an Atari that way, long ago. (I also used to tweak the IF, of my main set, to bring up the sharpness too!)
If you've got the cabling, plugging the composite video output into the luma for the S-video yields a very sharp monochrome display. (This is what I use most of the time.)
It's not too tough to suppress the color. Maybe that should be a parameter as well. Would significantly improve monochrome displays on most TV's.
potatohead said...
@Hippy: Quality and implementation there?
Hope that's a good thing!
I'm afraid I can't work out the semantics of that, if it's a praising or criticising comment ( I willingly take either )
That was really just a quick demo to show colours can be altered rather than anything else. In my modified driver I am having all sorts of weird problems when I change colors with artefacts to loss of sync. As you commented on timing issues I could be running into that; delete the color setting assembler code and it works okay.
A question I do have ...
CON CALC_overscan = 448
CON CALC_backporch = 208 + CHOOSE_horizontal_offset
What does the 448 represent and where is it derived from, and likewise the 208.
Getting the vertical lines per frame etc and frame sync for PAL is easy(ish), but I'm struggling to work out the horizontal porches/borders.
The best comments are in the 12 file. (need to rename those, and will on the next go around.)
On an NTSC scanline, there are a number of clocks. At 160 pixels of horizontal resolution, taking the safe area into account, there are 16 of those per pixel.
Now that I look at the code segment you've posted, I'm wondering if I didn't post up the wrong version last time. It should look like this, which will answer your query:
'core video timing constants, palettes and such, should not need editing at all
CON NTSC_color_frequency = 3_579_545
DAT NTSC_color_freq long NTSC_color_frequency
CON NTSC_hsync_clocks = 624
DAT NTSC_hsync_VSCL long 160368
DAT NTSC_control_signal_palette long $00_00_02_8a
DAT NTSC_hsync_pixels long %%11_0000_1_2222222_11
CON NTSC_active_video_clocks = 3008
DAT NTSC_active_video_VSCL long NTSC_active_video_clocks
CON NTSC_lines_per_frame = 244
'This area is stuff you edit for the pixel sizes, horizontal and vertical
'If this setup is for a bitmap driver, one can just key in pixel multiples of 8 and forget the char constant
CON number_of_chars_per_line = 20.0 'needs to be a float
CON horizontal_pixels = number_of_chars_per_line * 8.0 'needs to be float and multiple of 8
CON number_of_character_rows = 24 'number of lines of text total on screen
CON vertical_pixel_height = 1 'number of scan lines high (not active right now)
'Optional Edits below here
'Edit these to adjust the picture, their ranges depend on number of chars defined above
CON horizontal_offset = 0 'place your picture along the x axis + moves image right x # of clocks
CON vertical_offset = 0 'place your picture along the y axis + moves image down x # of scanlines
CON overall_image_size = 200.0 'Modify this to change picture width (about +-200 range)
'Both of these work in clocks, and depend on the clock speed of your prop, and number of chars defined above
'Start small, and work up until sync breaks to find limits.
'No edits required below here!!
'This section calculates the pixel clocks necessary, adjusting active video size as needed
CON INT_horizontal_pixels = TRUNC(horizontal_pixels) '& %111_1111_1000
CON clocks_per_active_scan_line = (ROUND((2360.0 + overall_image_size) / horizontal_pixels) * INT_horizontal_pixels)
CON clocks_per_pixel = clocks_per_active_scan_line / INT_horizontal_pixels
CON number_of_active_scan_lines = number_of_character_rows * 8
'Here the waitvids, for displayed pixels are setup (active user video area)
CON bytes_per_line = INT_horizontal_pixels / 8
CON waitvids_per_line = bytes_per_line
CON clocks_per_waitvid_frame = clocks_per_pixel*8
DAT CALC_user_data_VSCL long (clocks_per_pixel) << 12 + clocks_per_waitvid_frame
'After all that is settled, we must define the horizontal overscan from what's left!
CON overscan = 3008 - clocks_per_active_scan_line 'that's the horizontal border total
CON color_correction = (overscan / 2) // clocks_per_pixel
CON backporch = (overscan / 2) + horizontal_offset + color_correction 'left side border
CON frontporch = (overscan - backporch) 'right side border
'And the vertical overscan too...
CON vert_overscan = 244 - number_of_active_scan_lines 'That's the vertical border total
CON vert_backporch = (vert_overscan / 2) + vertical_offset 'top border
CON vert_frontporch = (vert_overscan - vert_backporch) 'bottom border
Basically, there are 3008 active video clocks per scan line. That's borders, safe area, the whole works. There are 624 clocks per HSYNC to complete the scanline.
That 448 is the result of subtracting the number of clocks consumed by the active video area, and borders. I've since made that a function of how many pixels are being asked for in the later versions. The latest drivers should allow variable numbers of characters per line, from 10 to almost 70, in the two color per screen mode, for the HUB based 2.x driver. It's 10 to 40 for the 3.x because of the additional logic required in that use case.
Cardboardguru posted up a set of constants, similar to this one, with his SIMPLE_NTSC demo / tutorial. I took it and worked out the math for flexible pixel timings, which appears above. That is for fixed color timing though. It's more complex for interlaced color.
I've almost got the above code perfect. There really are only two keyed in numbers for timing calcs, and it's really only because I didn't use the labels where I could have. Didn't see it until just now. The 244 is defined above as number of scan lines / frame. That label could be plugged into the calcs below. The 3008 is number of active clocks and can be handled the same way.
I did the math based approach, as opposed to just plugging in values that would build the scanline I want, for two reasons:
1. Translate that into assembly, so the driver can evaluate those every frame, for run time changes.
2. Permit multi-mode drivers.
eg: maybe have 4 lines of characters at bottom of screen, upper portion being bitmap display. Both of these could vary in terms of overall resolution, chars / line. At some point, I thought maybe the BASIC could be modified to run in that mode, thus letting people draw lines, etc... in the graphics area (maybe do a 160x96 full color or 4 color), while editing / writing in the text area.
Enough has been defined to permit this, given the fixed color timing. Before engaging in that, I really am gonna go for the interlaced timing, then build some more flexible, low memory foot print drivers.
I looked at PAL too. Will be very curious to see your PAL example. Ideally, learn from it and make this thing a multi-mode driver that will see a lot greater use. The 8x8 really is ideal for TV. Love the look of the Parallax ROM font, but it's information density is just too low for me.
Whoops! Just re-read through these definitions. There is one more. The 2360 is the number of clocks in the NTSC safe area. That's really where the clocks / pixel come from. If you've 160 pixels, there are 16 clocks / pixel, thus allowing the Propeller to do it's thing and generate 16 hues. If you've got 320 pixels being drawn, then there are only 8 clocks per pixel possible, and that's the jagged edges seen on contrasting colors. (don't forget to add 200, for a total of 2560 clocks for the graphics area)
What the Propeller actually does, in this case, is shift the pixel information to the nearest pixel, then it generates the correct hue information anyway. It's up to the driver builder then to make sure color phase alternates by 8 clocks, every other scan line to interlace the colors, for the full 320 pixels.
Anything less than 16 clocks / pixel, will show color artifacts on NTSC. Additionally, any high contrast transition will trigger this as that signal gets interpeted as color information. So, the edges of the text are gonna get hues associated with them, which brings us back to the whole pick colors that are the same HUE, different in INTENSITY bit, for the fewest of these artifacts, or suppress the color completely, leaving a pretty good monochrome display.
For your PAL timings, I would work thus:
Determine what one clock is.
Derive your total number of scanline clocks, that's the core you work from to derive the rest of the scanline. Determine how long a HSYNC pulse is, and subtract that leaving the active video area. (borders and all)
Determine your safe area number of clocks. Then, for a given number of pixels, you know the clocks per pixel, which helps setup the waitvid frame. (It's best to stick to multiples of 16 for this, or you end up with having to round things out in the borders to get stable timing, and you will get artifacts that vary across the screen. Subtract that from the active area, and now you have the size of the borders. Divide by two, to establish the border timings, for both left and right, adding an offset to the left one for horizontal positioning.
For the vertical, determine number of scanlines. You will be doing a non-interlaced display, because of flicker. So that's half the PAL standard. From there, determine the number of scanlines required to contain the safe area. This is more on PAL, so you can add a coupla character rows, or just leave a bigger border. The 12 driver is variable, so that should be cake to adjust.
Build your VSYNC, then it's just a matter of writing a bunch of blank lines to get your top border, draw your active video area, with graphics in it, then write out a bunch more of blank scans for the bottom border, then the VSYNC.
One aspect of PAL, I don't yet get, is the alternatiing color phase every other line. Might want an odd number of scanlines to make that just happen as it needs to. I'll be doing the same thing for the NTSC to get the color to alternate every other frame as well. Right now, it's even. Most all displays will tolerate these differences, and depend on them for interlaced displays.
On NTSC, there is an additional complication in that the left border needs to be a multiple of the pixel clock, for artifacts to be consistent. Not terribly important for this driver, but pretty darn important for bitmap ones, if people are gonna use sub-pixels to get more than the standard propeller colors. I do not believe this is necessary for PAL, so your calcs should be simpler there.
I've got the overall image size parameter added, which defaults to 200 clocks, for a total of 2560. Wanted some adjustment possible there. On some of the higher character counts, reducing that number packs them closer together, letting them all fit on the display safe area. Really just for monochrome, but that's how I did the 64 chars / line screenie above.
@ potatohead : Thanks for the info, and I can see I've got a bit of studying to do here but I've got a reasonably good grasp of bit banging non-color PAL video with a PIC 16F88 so it should work out in the end.
Thanks for the pointer to Cardboardguru's SIMPLE_NTSC. I'll tack that down and take a look at it.
My artefact / sync glitches are fixed; boiled down to a timing error in the draw_pixel routine. I removed the pre-calculation for 'fontsum' to simplify things ( to aid my understanding when starting ) and it worked fine. Putting the color altering code in meant too much execution time and >splat<
potatohead said...
Additionally, so many good things have happened! Guess it's gonna have to be put together in a better package. Hippy's reverse code is a great piece. I was just using OpenOffice to do this. That means a build_font_table procedure, which has been done. Oldbitcollector has done an ASCII sort, which is largely a cut 'n paste, but for Hippy changing the colors to be run-time. That's not a tough one either, but will have to wait, on my part. The port of TV-Text is awesome too. All combined make for a totally different looking release!
Totally. [noparse]:)[/noparse] Anyone doing a merge of the various code and doing this yet? I can take a stab at this much later tonight, but I'd like to make sure that I don't duplicate someone else's work if they're doing this as well. [noparse]:)[/noparse]
Oldbitcollector said...
I've been dancing "successfully" in new territories with spin, but I'd love it if someone would take on the job of merging everything.
All right, I'll see what I can do to merge, refactor, and clean up this stuff, though I can't test on the demoboard -- is anyone here willing to test the refactored code on a demoboard?
I've been working on the merge, however Hippy's changes do not work on the Hydra for some reason. I've run a diff, and I can't see what is different that would cause it not to work on a Hydra or display on my television. However, Oldbitcolelctor's TV_driver modifications work perfectly when I use the original char_mode_08 driver from the first post.
13a14,18
> Hippy 2007-10-20 ...
>
> Base pin of TV now passed as param : Use 12 for Demo Board, 24 for Hydra, or XX for 'whatever'
>
> Not tested on Hydra, works on Proto Board wired with TV on P12-14
16,19d20
< CON
< ' Set up the processor clock in the standard way for 80MHz
< _CLKMODE = xtal1 + pll8x
< _XINFREQ = 10_000_000 + 0000
20a22,25
>
>
> CON
>
90c95,120
< initialization 'set up VCFG
---
> initialization
> 'get parameters from parameter block, and pass them to COG code here
>
> mov C, PAR ' get parameter block address
> rdlong A, C ' get screen address
> mov bmp, A ' store another copy
>
> add C, #4 'index to fonttab address
> rdlong fonttab, C 'store it
>
> add C, #4 'index to mode value
> rdlong pixel_mode, C 'store it
>
> add C, #4 'index to colors value
> rdlong colors, C 'store them...
> mov fat_mode, colors 'set 16 bit mode
>
> add C, #4 'index to base pin number
> rdlong A, C
>
> and A,#%1000 ' top or bottom nibble
> IF_NZ mov A,#%0_01_000_000 ' top nibble
> or A,#%0_10_011_000
> mov vcfg_2_color_mode,A
> or A,#%0_10_111_000
> mov vcfg_4_color_mode,A
93,94d122
< movs VCFG, #%0000_0111 ' VCFG'S = pinmask (pin31: 0000_0111 : pin24)
< movd VCFG, #3 ' VCFG'D = pingroup (grp. 3 i.e. pins 24-31)
96c124,135
< movi VCFG, #%0_10_111_000 ' baseband video on bottom nibble, 2-bit color, enable chroma on broadcast & baseband
---
> mov A,#%0000_0111 ' mask top or bottom pins
> IF_NZ shl A,#4
> movs VCFG, A ' VCFG'S = pinmask (pin31: 0000_0111 : pin24)
>
> rdlong A, C
> shr A,#3
> movd VCFG, A ' VCFG'D = pingroup (grp. 3 i.e. pins 24-31)
>
> movi VCFG, vcfg_4_color_mode
>
>
> ' baseband video on bottom nibble, 2-bit color, enable chroma on broadcast & baseband
98c137
< ' %x_10_x_x_x_xxx : Composite video to top nibble, broadcast to bottom nibble
---
> ' %x_11_x_x_x_xxx : Composite video to top nibble, broadcast to bottom nibble
103a143,145
> rdlong A,C
> mov tvport_mask,#%01111
> shl tvport_mask, A
119,135d160
<
< 'get parameters from parameter block, and pass them to COG code here
<
< mov C, PAR ' get parameter block address
< rdlong A, C ' get screen address
< mov bmp, A ' store another copy
<
< add C, #4 'index to fonttab address
< rdlong fonttab, C 'store it
<
< add C, #4 'index to mode value
< rdlong pixel_mode, C 'store it
<
< add C, #4 'index to colors value
< rdlong colors, C 'store them...
< mov fat_mode, colors 'set 16 bit mode
<
164c189
< movi VCFG, #%0_10_011_000 'two color mode
---
> movi VCFG, vcfg_2_color_mode 'two color mode
212c237
< movi VCFG, #%0_10_111_000 '4 color mode
---
> movi VCFG, vcfg_4_color_mode '4 color mode
303a329,330
> vcfg_2_color_mode long %0_11_011_000
> vcfg_4_color_mode long %0_11_111_000
Are you going to include the separated font files so we can switch fonts?
Also are you going to adapt Char_Mode_08 to allow for both two color & multicolor fonts?
Attached is my 'composite driver' which directs output to a number of places. The demo shows how it can be used with the standard TV_Text plus the 8x8 driver.
The top-level object is AiChip_TvText_Demo_001.spin, edit to select the TV_PIN and uncomment the CON TV_MODE setting to use. FONT_0 is Atari, FONT_1 is CBM. It's still not tested on anything other than Pin 12 and PAL 8x8 not implemented yet.
The main 8x8 video handling is split between AiChip_SmallFont_001.spin ( Spin ) and AiChip_SmallFont_Driver_001.spim ( PASM ). It allows 16 text colours, fixed background. I had some problems moving from a word array screen buffer to a long array to allow any colours so I started again, but I will be changing that later. The fonts in the .Zip are modified versions of the Atari and CBM to use the characters I need.
None of this would have been possible without all the work done here, so many thanks.
Wes Brown said...
Ha! You've yanked the rug out from some of my integration efforts and done them yourself! [noparse]:)[/noparse]
But no biggie, I'll take a look at what you've done and see what else I can do to help clean things up.
-Wes
I've more taken a step sideways and a step backwards. It's a much more basic driver in many ways and tailored for my ultimate application, a serially controlled video terminal with some extra goodies. Apart from getting fore and background colours working I don't see much changing with it after that, so the original is still really the reference design.
Mind posting a simple reference of how to call color changes in the 40x25 text mode? Edit:
Ah, Byte 0-16, Got it..
Like that binary graphic too! Nice touch.
BTW: I've repaired a small issue with the CBM font. The file is attached.. Broken ) fixed.
Any chance either you or Wes will release a 'lite' version of this? This thing appears to be
able to make breakfast with toast in the morning! Nice work!
If Doug keeps going in the direction I think he's going with this (Hydra thread) with Sprites, etc.
This could make a nice prop-based video chip in it's own right. Something akin to the VIC chip
used in the Commodore.
I'd dedicate a prop for that.. [noparse]:)[/noparse]
Oldbitcollector said...
Any chance either you or Wes will release a 'lite' version of this? This thing appears to be
able to make breakfast with toast in the morning!
New attachment with even more bloat but also a lite version. Just load AiChip_SmallText_Demo_001.spin and that's the smallest 8x8 I can produce at the moment. With the demo code itself and one of the fonts removed it drops down to below 600 longs of code. You would have to add back in str(), dec() etc to return it to TV_Text drop-in replacement.
Ah, just what the doctor ordered... sweet.. Looks like it can drop a couple hundred more longs just be selecting the exact
font desired in the "AiChip_SmallFont_002" file.. Very nice...
From what I can tell at a glance the basic functions are still in tact... The demo portion appears to still be in place.
The demo here slightly changed because the number formatting routines have gone ( hence no pretty scrolling display ), but the functionality is pretty much the same.
Added : BTW, has anyone gotten it working on a Hydra yet ?
Oldbitcollector said...
Wicked thought just occurred to me...
If Doug keeps going in the direction I think he's going with this (Hydra thread) with Sprites, etc.
This could make a nice prop-based video chip in it's own right. Something akin to the VIC chip
used in the Commodore.
I'd dedicate a prop for that.. [noparse]:)[/noparse]
Oldbitcollector
I have very little spare time, but I've been thinking about that very thing. The design I have in mind would make use of external RAM for display memory so it could be shared with an external CPU like a 65C02 or a 65C816. Most of the prop's pins would be dedicated to address and data buses. One pin that generates a square wave at a few MHz would be used as a clock signal by the 65C02. All external memory access would be done when that signal is low, so that the old Apple 2 / C64 / Atari trick of two-phase DMA could be used. You'd also need another pin that would go low when accessing memory, to force the CPU to tristate its buses when the prop is reading character, font or pixel data. Finally, a pin that generates a pulse at the bottom of each frame (or when a particular scanline is reached) can be used to implement raster tricks.
I've done some basic math and I believe that with plain 70ns SRAMs that should be quite possible. I'm currently trying to work out if it would be a better idea to have one cog do all the work, or to have two cogs in a producer-consumer arrangement, where one cog is always outputting video data, and asking for more pixel data when it needs it; these pixels would be supplied by another cog, whose job is managing the various bus and signal pins, reading data from SRAM, doing palette lookups and feeding the cooked pixels to the painting cog when asked.
While you're thinking about this, take a look at some of the documentation floating online about the Atari CTIA and Antic chips. The two combined chips implemented a completely programmable display (you could have some scanlines at high resolution and few colours, and others at low resolution and more colours, different palettes per scanline, all sorts of cool stuff). This was state of the art in the late 70s when it came out.
Post Edited (Fabian Nunez) : 10/25/2007 6:16:11 AM GMT
hippy said...
Added : BTW, has anyone gotten it working on a Hydra yet ?
Works beautifully out of the box on a Hydra once the correct timing and pins have been set. Taking a look at your code and comparing it to the reference standard to see what I can pick out and merge. [noparse]:)[/noparse]
I'll likely write a TV_driver for this too.
Do we have a wishlist of features that we'd like to have in the unified and merged reference driver?
-Wes
Post Edited (Wes Brown) : 10/25/2007 9:20:07 AM GMT
Comments
displayb[noparse][[/noparse]index] := ($da + (c / 4)) | 2
Yes, I've noticed that if I alter the colors a bit that the color smearing effect can be minimized.
using: params(3) := $000CeFa brings it down to just M's and W's for the most part.
@potatohead: Did I understand that you were going to adjust params to be able to be called on the fly to
allow for changes in the color at any time? Or have I just not gotten far enough in my understanding yet?
(Finally figured out the bits to get this far, please add to documentation.) Still trying to digest all the info
you PM'ed me. [noparse]:)[/noparse]
Don't suppose that someone has created an index of colors?
Oldbitcollector
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Buttons . . . check. Dials . . . check. Switches . . . check. Little colored lights . . . check.
— Calvin, of 'Calvin and Hobbes.
Yes, sort of. Start with this in char_mode_08_TV.spin ...
That will alternate every character column colour.
To have an array of colours per char which is what I was after you'll need to pass a pointer to the array in and update the :darw_pixels routine. My code is so different now to the original driver that posting my code to do that will not help you, and I've not implemented that part yet.
@Wes: Changing the divisor doesn't seem to help very much on my 1702 monitor
I've been discovering color combinations that work and keeping track of them.
Not sure what index + 2 is doing, altering it has no effect.
Pleasantly, the smearing effect appears to be GONE in 16 bit mode...
May have spoke too soon, but it does appear to be lessened.
Oldbitcollector
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Buttons . . . check. Dials . . . check. Switches . . . check. Little colored lights . . . check.
— Calvin, of 'Calvin and Hobbes.
Post Edited (Oldbitcollector) : 10/23/2007 2:04:42 PM GMT
I thought I had pasted a CLUT (color lookup table) into the quickie demo program. Just checked and saw it isn't there. I've got a class to teach this friday --it's a new one, so I'm prepping like a mad dog. Won't have any real Propeller time until this weekend. Was sick, this last one!
The assembly language driver does not do a color lookup. Takes too long --at least that's the case at the moment. I've some ideas on how to address that, but it's gonna be a rewrite essentially. I think there is time during the sync, to grab a scanline full of chars. If so, maybe there will be time to do color mapping in the driver itself.
So, one must handle colors properly in their code that starts up the driver.
Additionally, so many good things have happened! Guess it's gonna have to be put together in a better package. Hippy's reverse code is a great piece. I was just using OpenOffice to do this. That means a build_font_table procedure, which has been done. Oldbitcollector has done an ASCII sort, which is largely a cut 'n paste, but for Hippy changing the colors to be run-time. That's not a tough one either, but will have to wait, on my part. The port of TV-Text is awesome too. All combined make for a totally different looking release!
There is a table of non-sync colors on the propeller wiki. Here is the link: http://propeller.wikispaces.com/Colors
That can be put into dat statements thus:
byte byte $02, $03, $04....
Coupla things about that table. The intent was to map the colors in an easy to grok fashion. So, lower three bits (0-7) are intensity, with the highest Propeller intensity duplicated a few times. That's the $07 repeated.
The colors follow, hue by hue, using the upper bits to specify hue. That leaves room for only 15 hues, so one of the blues is not included. Those numbers are included below the CLUT, and can be traded for another hue, if desired.
For each hue, the very darkest one might be a problem, as will the very brightest ones. All of my TV's displayed these, so I thought it was good. If that's not the case, that table can be cut down to limit intensities to the safe 5, which are 02 - 06.
I included all the colors possible, that had a good chance of displaying correctly, should somebody want to push it. A more conservative (and likely safer table) would eliminate the low intensity hues, along with the highest intensity ones.
With the table in SPIN, one can use a simple color index, 0-127, to pick the colors and assign them with @@clut, to point to the table start.
That table applies to assembly code where one just blasts the screen memory bits to a waitvid, instead of operating on them. I've written the bitmap code and this character code the same way, so the same table can be used. The high-color bitmap program shows use of the table.
Wes has it spot on for the artifacting (color smearing). That's a big part of why the Commodore and Atari fonts almost never have single pixels standing alone. This driver uses fixed color timing on every scanline. That puts effective resolution at 160 pixels, which is half that required for a 40 char display. Packing the pixels together keeps artifacts to a minimum. White on blue is one of the very best choices, keeping that in mind.
One can really cut down on this artifacting by using the brightest blue, on dark blue. That syncs up all the color info more or less perfectly, keeping artifacts to an absolute minimum. That really applies to most any of the hues. Blue seems to be good on the eyes. I suspect this is because we have about a third of the blue receptors that we do red and green! BTW: that aspect of our physiology is used in video compression schemes. Reducing the detail level of the blue component results in almost no significant perception of image depredation! This is also why we have such a hard time with higher levels of detail being drawn in blue.
Best color combos are:
Text and background same hue, different intensity.
Text white or black, background low intensity hue.
From there it downgrades..
Text white, background black, or inverse.
Text one color, background another. (worst case)
Since Hippy is looking at PAL, I'll go back to work on getting this up and running with interlaced color. That will significantly improve readability. Artifacts will alternate every other scanline and frame, and will cancel out, leaving 320 pixels of color resolution. Thta 160 pixel limitation is the dots surrounding each colored char, most easily seen on contrasting hues.
Finally, I suspect some of the smearing comes from the TV filter, and off color combinations. (text and background different hue, or black.) If you cut the saturation down, contrast up, sharpness up (if your tube has that one), those effects will be sharply diminished. Used to run an Atari that way, long ago. (I also used to tweak the IF, of my main set, to bring up the sharpness too!)
If you've got the cabling, plugging the composite video output into the luma for the S-video yields a very sharp monochrome display. (This is what I use most of the time.)
It's not too tough to suppress the color. Maybe that should be a parameter as well. Would significantly improve monochrome displays on most TV's.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
Hope that's a good thing!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
I'm afraid I can't work out the semantics of that, if it's a praising or criticising comment ( I willingly take either )
That was really just a quick demo to show colours can be altered rather than anything else. In my modified driver I am having all sorts of weird problems when I change colors with artefacts to loss of sync. As you commented on timing issues I could be running into that; delete the color setting assembler code and it works okay.
A question I do have ...
CON CALC_overscan = 448
CON CALC_backporch = 208 + CHOOSE_horizontal_offset
What does the 448 represent and where is it derived from, and likewise the 208.
Getting the vertical lines per frame etc and frame sync for PAL is easy(ish), but I'm struggling to work out the horizontal porches/borders.
The best comments are in the 12 file. (need to rename those, and will on the next go around.)
On an NTSC scanline, there are a number of clocks. At 160 pixels of horizontal resolution, taking the safe area into account, there are 16 of those per pixel.
Now that I look at the code segment you've posted, I'm wondering if I didn't post up the wrong version last time. It should look like this, which will answer your query:
Basically, there are 3008 active video clocks per scan line. That's borders, safe area, the whole works. There are 624 clocks per HSYNC to complete the scanline.
That 448 is the result of subtracting the number of clocks consumed by the active video area, and borders. I've since made that a function of how many pixels are being asked for in the later versions. The latest drivers should allow variable numbers of characters per line, from 10 to almost 70, in the two color per screen mode, for the HUB based 2.x driver. It's 10 to 40 for the 3.x because of the additional logic required in that use case.
Cardboardguru posted up a set of constants, similar to this one, with his SIMPLE_NTSC demo / tutorial. I took it and worked out the math for flexible pixel timings, which appears above. That is for fixed color timing though. It's more complex for interlaced color.
I've almost got the above code perfect. There really are only two keyed in numbers for timing calcs, and it's really only because I didn't use the labels where I could have. Didn't see it until just now. The 244 is defined above as number of scan lines / frame. That label could be plugged into the calcs below. The 3008 is number of active clocks and can be handled the same way.
I did the math based approach, as opposed to just plugging in values that would build the scanline I want, for two reasons:
1. Translate that into assembly, so the driver can evaluate those every frame, for run time changes.
2. Permit multi-mode drivers.
eg: maybe have 4 lines of characters at bottom of screen, upper portion being bitmap display. Both of these could vary in terms of overall resolution, chars / line. At some point, I thought maybe the BASIC could be modified to run in that mode, thus letting people draw lines, etc... in the graphics area (maybe do a 160x96 full color or 4 color), while editing / writing in the text area.
Enough has been defined to permit this, given the fixed color timing. Before engaging in that, I really am gonna go for the interlaced timing, then build some more flexible, low memory foot print drivers.
I looked at PAL too. Will be very curious to see your PAL example. Ideally, learn from it and make this thing a multi-mode driver that will see a lot greater use. The 8x8 really is ideal for TV. Love the look of the Parallax ROM font, but it's information density is just too low for me.
Whoops! Just re-read through these definitions. There is one more. The 2360 is the number of clocks in the NTSC safe area. That's really where the clocks / pixel come from. If you've 160 pixels, there are 16 clocks / pixel, thus allowing the Propeller to do it's thing and generate 16 hues. If you've got 320 pixels being drawn, then there are only 8 clocks per pixel possible, and that's the jagged edges seen on contrasting colors. (don't forget to add 200, for a total of 2560 clocks for the graphics area)
What the Propeller actually does, in this case, is shift the pixel information to the nearest pixel, then it generates the correct hue information anyway. It's up to the driver builder then to make sure color phase alternates by 8 clocks, every other scan line to interlace the colors, for the full 320 pixels.
Anything less than 16 clocks / pixel, will show color artifacts on NTSC. Additionally, any high contrast transition will trigger this as that signal gets interpeted as color information. So, the edges of the text are gonna get hues associated with them, which brings us back to the whole pick colors that are the same HUE, different in INTENSITY bit, for the fewest of these artifacts, or suppress the color completely, leaving a pretty good monochrome display.
For your PAL timings, I would work thus:
Determine what one clock is.
Derive your total number of scanline clocks, that's the core you work from to derive the rest of the scanline. Determine how long a HSYNC pulse is, and subtract that leaving the active video area. (borders and all)
Determine your safe area number of clocks. Then, for a given number of pixels, you know the clocks per pixel, which helps setup the waitvid frame. (It's best to stick to multiples of 16 for this, or you end up with having to round things out in the borders to get stable timing, and you will get artifacts that vary across the screen. Subtract that from the active area, and now you have the size of the borders. Divide by two, to establish the border timings, for both left and right, adding an offset to the left one for horizontal positioning.
For the vertical, determine number of scanlines. You will be doing a non-interlaced display, because of flicker. So that's half the PAL standard. From there, determine the number of scanlines required to contain the safe area. This is more on PAL, so you can add a coupla character rows, or just leave a bigger border. The 12 driver is variable, so that should be cake to adjust.
Build your VSYNC, then it's just a matter of writing a bunch of blank lines to get your top border, draw your active video area, with graphics in it, then write out a bunch more of blank scans for the bottom border, then the VSYNC.
One aspect of PAL, I don't yet get, is the alternatiing color phase every other line. Might want an odd number of scanlines to make that just happen as it needs to. I'll be doing the same thing for the NTSC to get the color to alternate every other frame as well. Right now, it's even. Most all displays will tolerate these differences, and depend on them for interlaced displays.
On NTSC, there is an additional complication in that the left border needs to be a multiple of the pixel clock, for artifacts to be consistent. Not terribly important for this driver, but pretty darn important for bitmap ones, if people are gonna use sub-pixels to get more than the standard propeller colors. I do not believe this is necessary for PAL, so your calcs should be simpler there.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
Post Edited (potatohead) : 10/23/2007 5:21:35 PM GMT
I've got the overall image size parameter added, which defaults to 200 clocks, for a total of 2560. Wanted some adjustment possible there. On some of the higher character counts, reducing that number packs them closer together, letting them all fit on the display safe area. Really just for monochrome, but that's how I did the 64 chars / line screenie above.
Post above edited.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
Thanks for the pointer to Cardboardguru's SIMPLE_NTSC. I'll tack that down and take a look at it.
My artefact / sync glitches are fixed; boiled down to a timing error in the draw_pixel routine. I removed the pre-calculation for 'fontsum' to simplify things ( to aid my understanding when starting ) and it worked fine. Putting the color altering code in meant too much execution time and >splat<
Now working as expected.
Totally. [noparse]:)[/noparse] Anyone doing a merge of the various code and doing this yet? I can take a stab at this much later tonight, but I'd like to make sure that I don't duplicate someone else's work if they're doing this as well. [noparse]:)[/noparse]
-Wes
Oldbitcollector
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Buttons . . . check. Dials . . . check. Switches . . . check. Little colored lights . . . check.
— Calvin, of 'Calvin and Hobbes.
All right, I'll see what I can do to merge, refactor, and clean up this stuff, though I can't test on the demoboard -- is anyone here willing to test the refactored code on a demoboard?
-Wes
Oldbit
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Buttons . . . check. Dials . . . check. Switches . . . check. Little colored lights . . . check.
— Calvin, of 'Calvin and Hobbes.
needs to become ...
I mentioned that earlier but I don't have a Hydra or anything with same pin wiring which I can test it on.
That did the trick -- now your modified version works. [noparse]:)[/noparse] Okay, I'll finish integrating everything later today.
-Wes
Are you going to include the separated font files so we can switch fonts?
Also are you going to adapt Char_Mode_08 to allow for both two color & multicolor fonts?
(Just want to keep from duplicating work)
Oldbitcollector
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Buttons . . . check. Dials . . . check. Switches . . . check. Little colored lights . . . check.
— Calvin, of 'Calvin and Hobbes.
The top-level object is AiChip_TvText_Demo_001.spin, edit to select the TV_PIN and uncomment the CON TV_MODE setting to use. FONT_0 is Atari, FONT_1 is CBM. It's still not tested on anything other than Pin 12 and PAL 8x8 not implemented yet.
The main 8x8 video handling is split between AiChip_SmallFont_001.spin ( Spin ) and AiChip_SmallFont_Driver_001.spim ( PASM ). It allows 16 text colours, fixed background. I had some problems moving from a word array screen buffer to a long array to allow any colours so I started again, but I will be changing that later. The fonts in the .Zip are modified versions of the Atari and CBM to use the characters I need.
None of this would have been possible without all the work done here, so many thanks.
But no biggie, I'll take a look at what you've done and see what else I can do to help clean things up.
-Wes
I've more taken a step sideways and a step backwards. It's a much more basic driver in many ways and tailored for my ultimate application, a serially controlled video terminal with some extra goodies. Apart from getting fore and background colours working I don't see much changing with it after that, so the original is still really the reference design.
Wow! I'm truely blown away!
Mind posting a simple reference of how to call color changes in the 40x25 text mode?
Edit:
Ah, Byte 0-16, Got it..
Like that binary graphic too! Nice touch.
BTW: I've repaired a small issue with the CBM font. The file is attached.. Broken ) fixed.
Any chance either you or Wes will release a 'lite' version of this? This thing appears to be
able to make breakfast with toast in the morning! Nice work!
Oldbitcollector
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Buttons . . . check. Dials . . . check. Switches . . . check. Little colored lights . . . check.
— Calvin, of 'Calvin and Hobbes.
Post Edited (Oldbitcollector) : 10/25/2007 1:41:49 AM GMT
If Doug keeps going in the direction I think he's going with this (Hydra thread) with Sprites, etc.
This could make a nice prop-based video chip in it's own right. Something akin to the VIC chip
used in the Commodore.
I'd dedicate a prop for that.. [noparse]:)[/noparse]
Oldbitcollector
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Buttons . . . check. Dials . . . check. Switches . . . check. Little colored lights . . . check.
— Calvin, of 'Calvin and Hobbes.
New attachment with even more bloat but also a lite version. Just load AiChip_SmallText_Demo_001.spin and that's the smallest 8x8 I can produce at the moment. With the demo code itself and one of the fonts removed it drops down to below 600 longs of code. You would have to add back in str(), dec() etc to return it to TV_Text drop-in replacement.
font desired in the "AiChip_SmallFont_002" file.. Very nice...
From what I can tell at a glance the basic functions are still in tact... The demo portion appears to still be in place.
Oldbitcollector
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Buttons . . . check. Dials . . . check. Switches . . . check. Little colored lights . . . check.
— Calvin, of 'Calvin and Hobbes.
Added : BTW, has anyone gotten it working on a Hydra yet ?
I've done some basic math and I believe that with plain 70ns SRAMs that should be quite possible. I'm currently trying to work out if it would be a better idea to have one cog do all the work, or to have two cogs in a producer-consumer arrangement, where one cog is always outputting video data, and asking for more pixel data when it needs it; these pixels would be supplied by another cog, whose job is managing the various bus and signal pins, reading data from SRAM, doing palette lookups and feeding the cooked pixels to the painting cog when asked.
While you're thinking about this, take a look at some of the documentation floating online about the Atari CTIA and Antic chips. The two combined chips implemented a completely programmable display (you could have some scanlines at high resolution and few colours, and others at low resolution and more colours, different palettes per scanline, all sorts of cool stuff). This was state of the art in the late 70s when it came out.
Post Edited (Fabian Nunez) : 10/25/2007 6:16:11 AM GMT
Works beautifully out of the box on a Hydra once the correct timing and pins have been set. Taking a look at your code and comparing it to the reference standard to see what I can pick out and merge. [noparse]:)[/noparse]
I'll likely write a TV_driver for this too.
Do we have a wishlist of features that we'd like to have in the unified and merged reference driver?
-Wes
Post Edited (Wes Brown) : 10/25/2007 9:20:07 AM GMT