Shop OBEX P1 Docs P2 Docs Learn Events
Graphics.spin usage help — Parallax Forums

Graphics.spin usage help

SRLMSRLM Posts: 5,045
edited 2009-10-19 05:35 in Propeller 1
I'm trying to use graphics.spin from the obex to make a nice display. I have hit two limitations though:

1) I'm testing it on this screen, and I notice that I have lots of unused space around the outside. I measured it, and there should be and additional ~60 x pixels and ~40 y pixels on the screen. What parameters do I need to change (and how would I know those are the parameters!) to fill up the entire screen?

2) In my testing, I notice that I can only set a box to four different colors: white, black, blue, and multicolored horizontal bars. Is there any way that I can get more colors? I notice that it initializes 64 colors, but 16 is more than enough for my application.

Below is my code. It's just a modified version of the graphics_demo where I left the graphics initialization part, and inserted my own graphics in the main loop.

Comments

  • potatoheadpotatohead Posts: 10,261
    edited 2009-10-18 00:30
    The colors are somewhat complex.

    Each tile has an address, which is in the screen array organized as words, one per tile. The upper 10 bits of each word is the tile address in the HUB memory. That's your bitmap. The lower bits form an index to entries in the colors array, which has 64 longs in it. The TV driver reads the screen array to detemine where to get the pixels from (HUB bitmap), and how to color them (entries in the colors array).

    Edit: this is pretty nice because the propeller waitvid wants just a pixels long and a colors long, and it then will draw 16 four color pixels, two bits per pixel.

    Back to the colors array, each of those longs contains 4 propeller colors, one byte each, for color 00, 01, 10, 11. You can run the graphics palette.spin, or look at the propeller wiki for some color information. Just know that not all byte values will result in a color. $02 is black, not $00! That's sync.

    There is a limitation of 4 colors per tile area. Each tile can be mapped to an entry in the colors array, so you can choose up to 64 four color combinations and assign them to any tile by modifying the screen array.

    I got this sorted by leaving everything as is, let it initalize. Then directly modify one of the colors array longs. I did a setting of all white. ($07) Then go and modify one of the screen array elements. Leave the upper bits alone, and only modify the lower 6 bits. If you do this correctly, one tile on the screen will be a white square, and you know you are good to go.

    Then, plan out your display and color use. Run the graphics commands to draw stuff, modify colors to get the colors you need prepped, then modify the screen array to assign them on a tile basis.

    When you are done, you will probably have rewritten the init portion of the graphics driver and will no longer need it. The init is kind of cryptic because a lot of math is used to paramaterize the display characteristics. The rainbow color is done in the init, and that's why there is a repeat to fill the colors array at the beginning.

    Another good exercise is to just strip down the colors init, until the same 4 colors are used for all the tiles. Once you have that down, it's pretty easy to just fill the colors array with the most used colors, then explicitly define a few where needed in tiles with odd colors here and there.

    Yes, it could be simpler, but that driver offers an awful lot of capability in a small package. It's worth knowing how it's used, simply because it's a very excellent balance between HUB RAM and display quality.

    I've a few comments about the other parameters:

    At the top, you've got number of tiles x and y.

    That is closely followed by display base and bitmap base. As the driver is written, it's double buffered. What ever you draw in bitmap, ends up copied to display once per frame, so no flicker is seen. Depending on your display, you might want to make both of these the same to cut the display memory in half.

    Go all the way to the bottom. tvparams is read by the TV driver, and will respond to change you make in graphics_demo. Now, zip all the way back to the top. That's where the comments for those are.

    Look at the VAR section, and you will see brief comments for what they do.

    I think the ones you need are: tv_hx, tv_vx.

    Bear in mind, the default settings take the NTSC safe area into account. This is about 20 percent of the display area that is not always seen on all devices. The older the device, the larger this area is, up to 20 percent. Since you are working on a nice, unmounted LCD, you can see that as "wasted". Go ahead and expand your display with those parameters, just know it's not always going to be seen on everything.

    $02, $03, $04, $05, $06, $07                      Six intensities
    $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
    
    



    from: http://propeller.wikispaces.com/Colors

    There is a picture there with a lot of colors on it. Those were done with tricks. However, the table I just posted, and the nice strip along the bottom, along with the big patches on the right, are useful to understand what numbers do what. The wiki text has enough explanation to go from there. I would add that looking at that strip at right corresponds to the first entries on the table. Each hue is a different line on the table, and I missed a few blues when I did it, and those are in the wiki as a few values not seen in the table.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Propeller Wiki: Share the coolness!
    Chat in real time with other Propellerheads on IRC #propeller @ freenode.net
    Safety Tip: Life is as good as YOU think it is!

    Post Edited (potatohead) : 10/18/2009 12:40:52 AM GMT
  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2009-10-18 07:57
    SRLM,

    See if the attached demo helps...

    If you take a look at the init color section, you will see that the color assignment ranges from 0 to 63 for a total of 64 colors. Don't let this confuse you this actually represents a palette. Each palette can contain 4 colors that you can select through the graphics routines as colors 0 to 3. Here is a breakdown of how the 'palette' assigns each color to the coresponding number 0 to 3....

      'init colors
      [b]repeat[/b] i [b]from[/b] 0 to 63
        colors[noparse][[/noparse]*i] := $02_02_02_02                           'Make entire screen black
    {
                      Color 3
                      ││ Color 2
                      ││ ││ Color 1
                      ││ ││ ││ Color 0
                      ││ ││ ││ ││ 
        colors[noparse][[/noparse]*i] := $02_9D_BB_2A
    
    Examples: (See Palette Demo for [b]other[/b] available colors)
      BB RED
      2A Dark BLUE
      02 BLACK
      5B GREEN
      9D YELLOW
      CD PINK        
      FC PURPLE
      BC ORANGE
      04 GREY
      3C Light BLUE
    }
    
    
    






    The next item that needs to be broken down is the tile assignment to the screen. In the graphics demo there are 16 X tiles and 12 Y tiles for a total of 192 tiles. A Palette can be assigned to any of the 192 tiles. One palette can even be assigned to multiple tiles (All of them if you wish).

    So the trick is to break down this line of code...

    screen[noparse][[/noparse]dy * tv_hc + dx] := display_base >> 6 + dy + dx * tv_vc + ((dy & $3F) << 10)
    
    



    display_base >> 6 + dy + dx * tv_vc + ((dy & $3F) << 10)

    display_base = $5000 or ... %01010000_00000000

    Shifting it right by 6 makes it ... %00000001_01000000

    dy+dx*tv_vc ... This codes the cell location you want to use the color at.

    For the demo this value is 12 and 16, dx*tv_vc will range fro 0 to 191

    Next we specify which color palette we want to use for the cell location.

    (dy & $3F) just ensures that we keep the values between 0 and 63 since we only have 64 color
    palettes to begin with.

    the << 10 shifts this value to the left by 10



    So, it might be easier to look at it this way...

    Display_location := display_base >> 6
    Cell_location_for_New_Palette := Py + Px * tv_vc
    palette_selection := ((selected_palette & $3F) <<10)

    screen[noparse][[/noparse]Py * tv_hc + Px] := Display_location + Cell_location_to_Assign_New_Palette + palette_selection



    ....Ok, so it still looks like a mess.... in the attached demo, I have made this a little easier with a routine that looks like this...

    PUB AssignPalette(_x,_y,Palette)
        _x := 0 #> _x <# (tv_hc - 1)
        _y := 0 #> _y <# (tv_vc - 1)
    
        Palette := (Palette & $3F)  
    
    '                             {Display location} + {screen position} + {Palette}
        screen[noparse][[/noparse]_y * tv_hc + _x] := display_base >> 6 + _y + _x * tv_vc + Palette <<10
    
    



    ...it basically does what is described above, allowing you to enter the X and Y tile screen position which ends up translating to a number between 0 and 191 and specifying a palette you want to assign to that tile.


    Note:
    In the original Graphics Demo program, the Palettes are assigned as ROWS, since there are only 12 Y tiles. This means that only 13 of the 64 palettes are even used.

    Palette 0 is reserved for the outer most border






    Hope this helps! ... I had to break it down for myself this way so that I could get it straight.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.

    Post Edited (Beau Schwabe (Parallax)) : 10/18/2009 8:03:03 AM GMT
  • potatoheadpotatohead Posts: 10,261
    edited 2009-10-18 08:02
    This is a great effort, BTW.

    Thanks for adding to my rambling. This topic has been contributed many times, and I could not find my other thread where it got better treatment. Not as good as yours, but better!

    IMHO, that demo should be a sticky. The topic comes up at least once a month. Always varies too. I'm bookmarking it.

    SLRM, did you get there?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Propeller Wiki: Share the coolness!
    Chat in real time with other Propellerheads on IRC #propeller @ freenode.net
    Safety Tip: Life is as good as YOU think it is!
  • SRLMSRLM Posts: 5,045
    edited 2009-10-19 03:22
    1) Thanks both for your help! I think I've got how the colors works now, at least enough so that I can make it look the way that I want it to.

    2) I'm still struggling with the screen size. I changed tv_hx to 11 (+1 from before), and it stretched a box to fit. But there was still some blank space, and when I tried to increase it further or do the same for the vertical the screen just showed popcorn (static). Is there a way that I can add a tile or two to each dimension to get a better fit? I got it. The parts that need to be changed are where the x_tiles and y_tiles are, but it needs to be changed in both the constants and the call to the graphics start function.

    3) I'm also working on understanding the vector definition. I get that the first entry is a point, then followed by a series of lines that build off the last one. However, I'm not sure how to interpret the numbers. Shown below is the vector definition for a star. I pared it down to a point and a line, and played with the numbers. The second word in each pair is easy: make it bigger, the line is bigger. It's the first number that stumps me. I know the first part ($8000) is to define a line, and the second part is for an angle. But, changing the angle part changes the size of the line! I tried $8000 + fff and $8000 + 1fff, and they both resulted in a horizontal line, but the latter was shorter. Is there something I am missing? Nevermind: a vector is defined in polar coordinates...

    Thanks for your help!

    Post Edited (SRLM) : 10/19/2009 5:08:51 AM GMT
  • potatoheadpotatohead Posts: 10,261
    edited 2009-10-19 05:35
    You can modify x_tiles and y_tiles. Each tile is 16 pixels, I believe.

    Also, can you connect some other device, such as a DVD player? There is highly likely some small amount of blank area anyway, though on most LCD's I've used, there isn't all that much. Maybe 5 percent or so.

    The vertical takes some special adjustment, in that doubling it up requires a corresponding adjustment to y_tiles, or the signal sync does not make sense.

    Horizontal scaling with that driver is pretty sweet. It basically just works, barring some combination of speed requirements that exceed whatever Propeller clock it's running on.

    Vertical is on a scan line basis. So the scaling is either pixels one scan high, two high, three high, etc... This is coarse compared to what can occur horizontally. This is an artifact of how the signal is built in the driver.

    _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

    I just grabbed the TV driver, which graphics_demo initializes with the parameter block structure we discussed earlier.

    ht - maps back to x_tiles, vt - maps back to y_tiles.

    Look at the parameter block for the init variable names for the others, but this is what they mean:

    hx = horizontal scale x
    vx = vertical scale y

    ho = horizontal offset
    vo = vertical offset.

    It might be possible to bump the vertical offset to the point where the display is near top of screen, then add a tile to better fill the display.

    This driver also does some things during the porch lines. That is what gives it all the display flexibility. A very large number of the drivers written here don't do that. They run rather fixed timing, which then frees up compute time for doing other stuff, like text, sprites, colors, and other things. This driver has limits in terms of consuming the entire display because of that, and that's very highly likely the source of the popcorn. It doesn't have the time it needs to do the on the fly computations because too wide of a display means too short of a porch time.

    The porch time is that time after sync, where technically live pixels can be drawn, but is not part of the "active" and "safe" area commonly accepted as being visible on all such devices. Probably a 10 percent non display area is to be expected, because of these things. When the display is being used as a simple video display, most of it will be used as there really is no computation, and video signals generally occupy the entire pixel area horizontally, and a fair amount vertically, though not as much. This is to take advantage of newer displays where there is less "overscan", and nobody wants a black stripe, or bar on their TV, unless it's for formatting purposes, like 16:9, or something like that.

    One of the very cool things about this driver is the flexibility you do have within the display area. Basically, you can pick your horizontal resolution with the number of tiles used, then use the scale parameter and offset parameter to best fit that resolution to the display. If you don't need to crank it up, a lot of RAM can be saved.

    Vertically, it's more coarse. Since scaling is an even multiple of the scan line, you get either the number of default tiles, twice the tiles for interlaced, or half the tiles for non interlaced. This translates roughly to 96 or 100 pixels, 192 or 200 pixels, 384 to 400 pixels. I'm giving both numbers, because I'm not where I can check the driver doing 192, or 200 scan line, non-interlaced display. I think it does 192, meaning the lower vertical numbers would be in effect.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Propeller Wiki: Share the coolness!
    Chat in real time with other Propellerheads on IRC #propeller @ freenode.net
    Safety Tip: Life is as good as YOU think it is!

    Post Edited (potatohead) : 10/19/2009 6:18:17 AM GMT
Sign In or Register to comment.