Shop OBEX P1 Docs P2 Docs Learn Events
Beginner questions about rogloh's p2videodrv — Parallax Forums

Beginner questions about rogloh's p2videodrv

Hi all. I'm slowly trying to learn how to use rogloh's p2videodrv (thread) and I have questions. Let's start with this:

  1. How does one determine an appropriate _clkmode and _clkfreq?

For example, in complexdemo.spin2 (from p2videodrv0_91b), I see

  CLK108MHz   = %1_000100_0000011010_1111_10_00 '(20MHz/5) * 27/1 = 108   MHz

  _clkmode = CLK108MHz ' setup a default clock
  _clkfreq = 108_000_000

but in P2_CharacterMapDemo.spin2 (from Quick Bytes) I see

    _clkfreq  = 252000000 ' initial clock rate (would be changed for a given video mode)

and in helloworld.spin2 (from p2textdriver0.93) I don't see _clkfreq or _clkmode at all!?

What's going on here?

Comments

  • evanhevanh Posts: 16,430
    edited 2023-10-14 03:46

    From memory, sysclock frequency is set by the driver according to the screen-mode presets. Yes, very chaotic structures in the API.

    I once wrote a wrapper routine that automated the building of a custom screen-mode structure according to a desired clkfreq, resolution and refresh. It'll be somewhat out of date now I suspect.

    EDIT: I found this inserted into a more recent copy of the driver (p2videodrv.spin2), it might okay:

    PUB  computeCustomDvi(timing, p2freq, hres, vres, vfreq) : r | divisor, vblank, hblank, hfp, hbp
    {{
    So there is a total of four effective parameters to build complete HDMI timings from:
    1 - sysclock frequency (p2freq)
    2 - horzontal resolution (hres)
    3 - vertical resolution (vres)
    4 - vertical frequency (vfrq)
    
    Remaining timings are: (currently out of date, since there is now a bias toward a vblanking of 45)
    dotfrq (>= 25 MHz) = p2freq / 10
    htot = hres + 80
    hfp = 8
    hsw = 64
    hbp = 8
    vtot = dotfrq / (htot * vfrq)
    vblank = vtot - vres
    vsw = 2
    vfp = (vblank - vsw) / 2
    vbp = vblank - vsw - vfp
    negative hsync and vsync both
    }}
        p2freq #>= 250_000_000    'minimum DVI link speed
        divisor := 10             'fixed ratio dot-clock, DVI hardware is locked to 10:1
        vfreq #>= 10              'sane minimum
        hres &= $7f8              '8-bit range (x8)
        vres &= $7ff              '11-bit range
    
        vblank := vres / 10                     'kick-off with desired mid-range vblank
        vblank := 45
        r := divisor * vfreq * (vres + vblank)  'htot = dotfreq / (vtot * vfreq)
        hblank := (p2freq + r/2) / r - hres     'hblank = htot - hres
    '    hblank := ((hblank + 4) & $fff8) #> 80  'bound to min 80 hblank, multiples of eight
        hblank := hblank #> 80
    
        r := divisor * vfreq * (hres + hblank)  'vtot = dotfreq / (htot * vfreq)
        vblank := (p2freq + r/2) / r - vres     'vblank = vtot - vres
        vblank := 20 #> vblank <# 960           'bound blanking, possibly break vfreq
    
    '    hfp := ((hblank - 64) >> 1) & $7ff8     'multiples of eight
        hfp := (hblank - 64) >> 1
        hbp := hblank - 64 - hfp
        long[timing][2] := hres >> 3
        long[timing][2] |= (hfp & $7f) << 24    'hfp  (bit31 high for positive sync)
        long[timing][2] |= (64 & $ff) << 16     'hs
        long[timing][2] |= (hbp & $ff) << 8     'hbp
        long[timing][5] := ((hfp << 1) & $ff00) 'hfp
    '    long[timing][5] |= ((64 >> 4) & $f0)    'hs
        long[timing][5] |= ((hbp >> 8) & $f)    'hbp
    
        r := ((vblank - 2) >> 1) <# $ff
        long[timing][3] := vres
        long[timing][3] |= r << 23              'vfp  (bit31 high for positive sync)
        long[timing][3] |= 2 << 20              'vs
        r := (vblank - 2 - r) <# $1ff
        long[timing][3] |= r << 11              'vbp
    
        long[timing][0] := 0                    'use auto-compute of clock mode
        long[timing][1] := p2freq
    '    long[timing][4] := (divisor +< 256) ? (divisor << 8) : divisor
        long[timing][4] := $0CCC_CCCC+1         'DVI TMDS encoding hardware is wired for 10:1 only
        long[timing][6] := 0
    'Calculate final vertical scan frequency (in tenths of hertz)
    '    vblank := long[timing][3].[30..23] + 2 + long[timing][3].[19..11]
    '    r := (hres + 80) * (vres + vblank)     'htot * vtot
    '    r := (p2freq + r/2) / r                'vfreq = dotfreq / (htot * vtot)
        return timing
    
  • roglohrogloh Posts: 5,898
    edited 2023-10-15 09:06

    @mpark, your confusion is probably related to some detritus left lying around in demo code that you have found or just a result of my own sloppiness. I believe these days that typically the final P2 clock frequency and mode is being setup by the choice of video mode using the values in the first two longs of the selected timing structure, unless you configure the value of the clock frequency as 0 (as given in the information and logic below). It is good practice however for an application to setup a default P2 startup clock frequency before this video initialization step happens so it doesn't take too long to boot if it just defaults to the RC clock initially.

        ' Optional PLL adjustment logic:
        ' This code attempts to be flexible in that you can choose to have this driver setup the P2 PLL
        ' for the pixel frequency setup and optional clock mode indicated in the timing structure,
        ' or leave the clock alone and have it configured elsewhere.
        '
        ' Two longs are part of the timing structure: the new optional clock mode, and the new P2 frequency.
        ' These are used to determine what to do and one of these three cases will be handled:
        '
        ' (a) If the new P2 frequency is 0 or equal to the current P2 clock frequency nothing will be changed.
        '
        ' (b) If the new P2 frequency is non-zero and the clock mode is non-zero, then that clock mode and
        ' frequency will be used in a CLKSET operation called by this driver.
        '
        ' (c) If the new P2 frequency is non-zero and the clock mode is 0, an attempt is made to auto-configure
        ' the PLL based on the specified new frequency.  The crystal or input clock frequency are required to
        ' be specified as well as the tolerance in Hz.  The closest PLL settings are computed based on these
        ' criteria and will be used in CLKSET.  If the tolerance is not met then no PLL timing will be changed.
        ' Take that into consideration when setting up the tolerance and don't set values that are unachievable.
    
        newmode := long[timing][0] ' get new clock mode
        newfreq := long[timing][1] ' get desired frequency
        if newfreq and (clkfreq <> newfreq)
            if newmode == 0
                newmode := computeClockMode(newfreq)
            if newmode
                CLKSET(newmode, newfreq)
    
    <snip>
    
  • mparkmpark Posts: 1,315

    OK, thanks!

    @rogloh, question about versions: in p2textdriver0.93.zip, both p2textdrv.spin2 and p2videodrv.spin2 are version 0.92b according to internal comments, which is confusing. Meanwhile, the P2 Character Map Demo (Quick Byte) contains p2videodrv.spin2 version 0.93b. I'm surprised to see it there but not in your "P2 DVI/VGA driver" thread. Is there some other place you're publishing your code?

  • roglohrogloh Posts: 5,898
    edited 2023-10-16 12:06

    @mpark said:
    OK, thanks!

    @rogloh, question about versions: in p2textdriver0.93.zip, both p2textdrv.spin2 and p2videodrv.spin2 are version 0.92b according to internal comments, which is confusing. Meanwhile, the P2 Character Map Demo (Quick Byte) contains p2videodrv.spin2 version 0.93b. I'm surprised to see it there but not in your "P2 DVI/VGA driver" thread. Is there some other place you're publishing your code?

    Yeah it seems there was probably a missing one line version update in the files in version 0.93b (which I think was a simple VAR order change or something to get a newer flexspin build working again so I must have missed updating the lines in the file - my bad). The P2 Quick Byte one was probably something I'd given directly to VonSzarvas who did the Quick Byte demo when I provided him with some of the other graphics code he used. So it might have been changed locally in my tree but is not yet an official release but was just pending the next release. I'll have to see what exactly was different there.

    UPDATE: Just checked the version in the Quick Byte. It does include a later bug fix I found in VGA output mode with incorrectly enabled parallel output pins colliding with the DAC pins in some special cases and it looks like this code also made it into a memory driver demo according to the version comment in the file. So for now best to use that latest named version you found in the Quick Byte or if encounter any problems with VGA and want a fix. I'll need to release this fix officially at some point in my P2 video driver thread. Still on my (long) list of things to do...

  • mparkmpark Posts: 1,315

    Thanks @rogloh. Sorry for the late reply.

    Is there an example demonstrating how to get NTSC composite output with your driver?

  • There is probably something I wrote a while back that used composite, will just need to dig it up for you when I get a spare moment...stay tuned.

  • I found this old thing...it includes an older version of the video driver but hopefully gives you the basic idea of how to set it up. It can be setup for SVIDEO or Composite output depending on which initDisplay line you enable. If you want to use S-VIDEO you need to build a cable taking the signals from 2 P2 sequential pins (luma+chroma) from the base pin, while composite just uses the base pin.

    I am still working on improvements to NTSC/PAL pixel and timing quality using Chip's computations which I also found elsewhere in my folders as another NTSC demo but that might confuse you as it is in a state of flux right now and adds lots of computations and debug stuff initially.

    So see if this helps for now...

  • I have a version where I properly fixed the colorspace parameters (as good as they get, anyways). Rogers original ones were bad and Chip's parameters cause AGC issues in some devices. Will have to dig that out later.

  • mparkmpark Posts: 1,315

    Hey, I'm reviving this thread because I 'm still a beginner and I have another question. I have a program that starts with these constants:

    _clkfreq   = 252000000 ' initial clock rate (would be changed for a given video mode)
    MS_001   = _clkfreq / 1_000                                   ' ticks in 1ms
    US_001   = _clkfreq / 1_000_000                               ' ticks in 1us
    

    and everything works: debug() works, full duplex serial to prop term works, my timed loops--all good.

    BUT after I start up rogloh's video driver
    vid.initDisplay(-1, @display, VIDEO_TYPE, BASE_PIN, 0, 0, @linebuffer, LINEBUFSIZE, timing, 0, @region)
    I get gibberish from debug() and on prop term. I assume the driver is changing the clock speed but everything else is under the misapprehension that it's still 252000000.

    Anyway, my question is: How do I get the video driver to play nicely with debug and serial, and how do I compute MS_001?

  • Yes… Rogloh’s driver will change clkfreq to whatever it needs based on your VIDEO_TYPE parameters.

    One quick fix… Could your main code start with the same clk setting?

  • evanhevanh Posts: 16,430
    edited 2025-04-17 07:49

    I mostly use FlexC libs these days so haven't used debug() function much at all. More recently I know debug started using smartpin P63 to hold a copy of clock frequency for its internal use. I'm guessing one has to manually set this value, using a WXPIN, whenever the frequency is adjusted.

    ie: Straight after the vid.initDisplay() put:

        wxpin(63, clkfreq)
    

    Of course, you don't want to do this when debug is not active. It would mess up the rx side of comport config.

  • evanhevanh Posts: 16,430
    edited 2025-04-17 08:33

    Huh, does the job for Pnut, but not so for current version of Flexspin ...

    EDIT: Double huh! That manual setting of P63 above isn't needed as all. Debug from Pnut v46 can handle a sysclock frequency change without any manual copying. Looks like this is just Flexspin getting behind ... Looking back through Pnut's notes I see version 36 has the handling added, in Sept 2022. And the clkset() function does the copy to smartpin P63.

    mpark,
    I presume Flexspin is what you're using here?

  • mparkmpark Posts: 1,315

    @VonSzarvas said:
    One quick fix… Could your main code start with the same clk setting?

    Sure, but how do I get that number? [A few moments later...] OK, I plucked up some courage and looked through the video driver and found, for my desired video mode and resolution, an appropriate-looking number. I replaced 252 with 270 in my code and Bob's my uncle! Thanks, @VonSzarvas!

    @evanh said:
    I presume Flexspin is what you're using here?

    No, PropTool 2.7.0 (beta). Maybe I should upgrade.

  • evanhevanh Posts: 16,430

    @mpark said:
    No, PropTool 2.7.0 (beta). Maybe I should upgrade.

    Most definitely! V 2.9.3 is newest, dated May 2023 - https://www.parallax.com/package/propeller-tool-software-for-windows-spin-assembly-2/
    So it'll be based on the compiler engine from Pnut v39 - https://forums.parallax.com/discussion/171196/.../p1

  • roglohrogloh Posts: 5,898

    @VonSzarvas , thanks for responding to help @mpark. Just noticed this post today - would likely have responded also but was out all yesterday.

    This is one of those annoying cases that can trip you up. The top level SPIN2 file sets up a _clkfreq parameter that is used by objects and becomes the P2 frequency at startup time, but if it later changes on the fly based on some nested object, in this case my video driver, it will upset the timing of prior allocated COGs that already relied on _clkfreq for their own timing parameters when they are started. Best to simply start your top level code with the final video frequency in mind by assigning it to _clkfreq, or potentially start the VGA driver first and then spawn other COGs that always detect the current frequency when they compute any timing parameters they use. However any static CONstants using clkfreq used to compute timing are going to become troublesome in such situations if not solved the first way. It's a PITA to understand the first time if you don't know what's going on internally but not too bad to sort out once you know what's happening.

    Typically serial uart objects are affected for baud rates in these cases so you'll often get a visual indication of garbage being output to a console which is a good sign of a P2 clock setting mismatch problem.

    Also if the default (stock) timing doesn't suit, my driver has the ability to be configured with custom timing if you need to run at a specific P2 clock frequency (within limits). It's more tricky to setup as you need to recompute different v&h sync widths and blanking sizes etc, keeping line frequency and desired refresh rate to remain valid for the display device. The VGA output type offers flexibility there and most analog video monitors allowed a range of horizontal and vertical scanning rates. Don't always feel compelled you need to stick with stock VGA timing, although it likely gives the most compatibility with most existing monitors, especially devices that limit the number of modes they support, e.g. some home entertainment gear is far more restrictive in what input resolutions/timing it supports.

  • evanhevanh Posts: 16,430
    edited 2025-04-18 02:21

    @rogloh said:
    @VonSzarvas , thanks for responding to help @mpark. Just noticed this post today - would likely have responded also but was out all yesterday.

    This is one of those annoying cases that can trip you up. The top level SPIN2 file sets up a _clkfreq parameter that is used by objects and becomes the P2 frequency at startup time, but if it later changes on the fly based on some nested object, in this case my video driver, it will upset the timing of prior allocated COGs that already relied on _clkfreq for their own timing parameters when they are started. ...

    The other approach is to use the run-time value of clkfreq instead of clkfreq_. It eliminates that problem but does incur more run-time code of course.
    BTW: Don't use _clkfreq for anything other than the first CON. _clkfreq is the requested frequency, clkfreq_ is the actual compiled in frequency.

    Also if the default (stock) timing doesn't suit, my driver has the ability to be configured with custom timing if you need to run at a specific P2 clock frequency (within limits). It's more tricky to setup as you need to recompute different v&h sync widths and blanking sizes etc, keeping line frequency and desired refresh rate to remain valid for the display device. ...

    That's the intent of my first post of this topic - To automate the timings for a given display resolution and refresh. I'd love to know how well it works with displays other than the couple I use here.

Sign In or Register to comment.