Shop OBEX P1 Docs P2 Docs Learn Events
Digital Video Out 64006-ES (d) — Parallax Forums

Digital Video Out 64006-ES (d)

SaucySolitonSaucySoliton Posts: 482
edited 2019-02-04 02:57 in Propeller 2
What is the purpose of this board with engineering sample chips? Or is it mostly going to sit idle until the new silicon is out?

Did I miss the HDMI encoding software?

Maybe it could be used for high speed P2 to P2 communication.

EDIT:
The code right below is from Chip Gracey. Original post: forums.parallax.com/discussion/comment/1450905/#Comment_1450905 It's on page 10 of a currently 21 page thread, so easy to miss.

Comments

  • With current silicon (P2-ES) this spin2 demo works when 64006-ES(d) is connected to the top-left header pins (P0 to P7) and an HDMI-type monitor.


    con     base        = $1000         'base address of line bytes
            lineticks   = 800           'ticks per line
            linebytes   = lineticks * 10    '*10 for 10b output per tick
    '
    '
    ' HDMI display test for early P2 silicon with 20MHz crystal and
    ' P[7:0] connected to HDMI {R+, R-, G+, G-, B+, B-, CLK+, CLK-}
    '
    ' The next version of silicon will have TMDS hardware to compose LVDS stream on the fly.
    '
    dat     org
    
            hubset  ##%1_000001_0000011000_1111_10_00   'enable crystal+PLL, stay in 20MHz+ mode
            waitx   ##20_000_000/100            'wait ~10ms for crystal+PLL to stabilize
            hubset  ##%1_000001_0000011000_1111_10_11   'now switch to PLL running at 250MHz
    
            setxfrq ##$80000000     'set streamer to output on every clock
    
            mov dira,#$FF       'P[7:0] = {R+, R-, G+, G-, B+, B-, CLK+, CLK-}
    '
    '
    ' Write visible line into hub
    '
    vline       wrfast  #0,line_vis     'ready to write line data
    
            mov bal_r,#0        'reset balance accumulators
            mov bal_g,#0
            mov bal_b,#0
    
            mov z,##640         'write visible pixels
    .prep       callpa  #0*256/3,#pretty
            setbyte rgb,pa,#3
            callpa  #1*256/3,#pretty
            setbyte rgb,pa,#2
            callpa  #2*256/3,#pretty
            setbyte rgb,pa,#1
            call    #convert_rgb
            djnz    z,#.prep
    
            mov z,#16           'write pre-hsync
    .hpre       mov color_r,sync0
            mov color_g,sync0
            mov color_b,sync0
            call    #output_rgb
            djnz    z,#.hpre
    
            mov z,#16           'write hsync
    .hsync      mov color_r,sync0
            mov color_g,sync0
            mov color_b,sync1
            call    #output_rgb
            djnz    z,#.hsync
    
            mov z,#128          'write post-sync
    .hpost      mov color_r,sync0
            mov color_g,sync0
            mov color_b,sync0
            call    #output_rgb
            djnz    z,#.hpost
    '
    '
    ' Write invisible line into hub
    '
    iline       mov z,##640+16
    .hpre       mov color_r,sync0
            mov color_g,sync0
            mov color_b,sync0
            call    #output_rgb
            djnz    z,#.hpre
    
            mov z,#16
    .hsync      mov color_r,sync0
            mov color_g,sync0
            mov color_b,sync1
            call    #output_rgb
            djnz    z,#.hsync
    
            mov z,#128
    .hpost      mov color_r,sync0
            mov color_g,sync0
            mov color_b,sync0
            call    #output_rgb
            djnz    z,#.hpost
    '
    '
    ' Write sync line into hub
    '
    sline       mov z,##640+16
    .hpre       mov color_r,sync2
            mov color_g,sync2
            mov color_b,sync2
            call    #output_rgb
            djnz    z,#.hpre
    
            mov z,#16
    .hsync      mov color_r,sync2
            mov color_g,sync2
            mov color_b,sync3
            call    #output_rgb
            djnz    z,#.hsync
    
            mov z,#128
    .hpost      mov color_r,sync2
            mov color_g,sync2
            mov color_b,sync2
            call    #output_rgb
            djnz    z,#.hpost
    '
    '
    ' Output screen data over and over
    '
            rdfast  line_cnt,line_vis   'ready to loop-read visible line buffer
    
    .field      mov x,#480          'ready for 480 visible lines
    .vis        xcont   line_mod,#3     'output visible line
            cmp x,#1        wz  'if last line, update fblock to invisisble line
        if_z    fblock  line_cnt,line_inv
            djnz    x,#.vis
    
            mov x,#10           'ready for 10 invisible lines
    .pre        xcont   line_mod,#3     'output visible line
            cmp x,#1        wz  'if last line, update fblock to sync line
        if_z    fblock  line_cnt,line_syn
            djnz    x,#.pre
    
            mov x,#2            'ready for 2 sync lines
    .sync       xcont   line_mod,#3     'output visible line
            cmp x,#1        wz  'if last line, update fblock to invisisble line
        if_z    fblock  line_cnt,line_inv
            djnz    x,#.sync
    
            mov x,#33           'ready for 33 invisible lines
    .post       xcont   line_mod,#3     'output visible line
            cmp x,#1        wz  'if last line, update fblock to visisble line
        if_z    fblock  line_cnt,line_vis
            djnz    x,#.post
    
            jmp #.field
    '
    '
    ' Make pretty color from pa and z into x
    '
    pretty      mov x,z
            sca x,##round(256.0/480.0 * float($10000))
            add pa,0
            shl pa,#24
            qrotate #127,pa
            getqx   pa
        _ret_   bitnot  pa,#7
    '
    '
    ' Data
    '
    sync0       long    %1101010100     '
    sync1       long    %0010101011     '    hsync
    sync2       long    %0101010100     'vsync
    sync3       long    %1010101011     'vsync + hsync
    
    line_mod    long    $1080<<16 + linebytes   'RFBYTE streamer mode
    line_cnt    long    linebytes / 64  
    
    line_vis    long    base + linebytes*0  'visible line address
    line_inv    long    base + linebytes*1  'invisible line address
    line_syn    long    base + linebytes*2  'sync line address
    '
    '
    ' Convert 8:8:8:0 RGB into 10-byte TMDS pattern in hub
    '
    convert_rgb getbyte color,rgb,#3
            mov bal,bal_r
            call    #color_tmds
            mov bal_r,bal
            mov color_r,color
    
            getbyte color,rgb,#2
            mov bal,bal_g
            call    #color_tmds
            mov bal_g,bal
            mov color_g,color
    
            getbyte color,rgb,#1
            mov bal,bal_b
            call    #color_tmds
            mov bal_b,bal
            mov color_b,color
    
    output_rgb  mov x,#0
    .loop       shr color_r,#1  wc
            bitc    y,#7
            bitnc   y,#6
            shr color_g,#1  wc
            bitc    y,#5
            bitnc   y,#4
            shr color_b,#1  wc
            bitc    y,#3
            bitnc   y,#2
            cmp x,#5        wc
            bitc    y,#1
            bitnc   y,#0
            wfbyte  y
            incmod  x,#9        wc
        if_nc   jmp #.loop
    
            ret
    '
    '
    ' Convert R/G/B in color[7:0] into TMDS in color[9:0]
    '
    color_tmds  ones    bal_m,color     'ones > 4 || ones == 4 && !color[0]?
            cmp bal_m,#4    wcz
        if_z    testb   color,#0    wc  'c=0 for XNOR
    
            testb   color,#0    wz
      if_z_eq_c bitnot  color,#1
        
            testb   color,#1    wz
      if_z_eq_c bitnot  color,#2
        
            testb   color,#2    wz
      if_z_eq_c bitnot  color,#3
        
            testb   color,#3    wz
      if_z_eq_c bitnot  color,#4
        
            testb   color,#4    wz
      if_z_eq_c bitnot  color,#5
        
            testb   color,#5    wz
      if_z_eq_c bitnot  color,#6
        
            testb   color,#6    wz
      if_z_eq_c bitnot  color,#7
    
            ones    bal_m,color     'get bal_m
    
            bitc    color,#8
    
            sub bal_m,#4    wcz 'sign of bal_m into c, (bal_m == 0) into z
    
        if_nz   cmp bal,#0      wz  'get (bal_m == 0 || bal == 0) into z
    
            testbn  bal,#31     xorc    'get (bal_m[31] == bal[31]) into c
            wrc bal_sign        'get (bal_m[31] == bal[31]) into bal_sign
    
        if_z    testbn  color,#8    wc  'inv_m = bal_zero ? !m[8] : bal_sign
    
            bitc    color,#9        'finalize TMDS pattern
        if_c    xor color,#$FF
    
            shl bal_m,#1        'adjust bal
    
            testbn  color,#8    wc  
        if_z    jmp #.sum
    
            testb   bal_sign,#0 wc
            testb   color,#8    wz
      if_c_eq_z sumnc   bal,#2
    .sum    _ret_   sumc    bal,bal_m
    '
    '
    ' Data
    '
    color       res 1
    bal     res 1
    bal_m       res 1
    bal_sign    res 1
    
    bal_r       res 1
    bal_g       res 1
    bal_b       res 1
    
    color_r     res 1
    color_g     res 1
    color_b     res 1
    
    rgb     res 1
    
    x       res 1
    y       res 1
    z       res 1
    t       res 1
    
  • I'm not too worried, but couldn't get this to work with a TCL tv monitor. I tried adding aux power, that didn't solve it.

    I'll try other monitors and cables later
  • Update - works fine with the trusty old DSE monitor. I'm happy with that for now.
  • Update 2 - also works fine with an Acer T232HL. Just TCL holding out...
  • RaymanRayman Posts: 13,805
    So, that code is bit-banging HDMI? That's pretty neat.

    Is it just doing some test pattern? Can it display a full screen color bitmap, like the vga demos?
  • Here's the output (at a curious angle!)

  • It's working! Thanks, VonSzarvas.


    I haven't read all of the posts in the previous HDMI thread from November... If we could output 20 bytes at a time, that is 2 pixels. If they are doubled pixels, it's easy to have correct 1/0 balance at the end of each 2 pixel group. To run 480i, it's necessary to double pixels.
  • I finally received my P2-ES board and this HDMI board yesterday afternoon (don't ask), so I am definitely interested in trying out the various bitbang ideas we'd talked about in that long HDMI thread last year. Will first need to setup a suitable environment on a MAC or Linux system but the main problem right now it that it's great beach weather too for the next couple of days. Will see how far I get today. :smile:
  • RaymanRayman Posts: 13,805
    I looked at this code and think I see now that the output line is precalculated before display.
    It's still very interesting.
    With Hyperram, maybe could do image this way...
  • @Tubular try this on the TCL.
    
    ' http://forums.parallax.com/discussion/comment/1463078/#Comment_1463078
    con     base        = $1000         'base address of line bytes
            lineticks   = 800           'ticks per line
            linebytes   = lineticks * 10    '*10 for 10b output per tick
    '
    '
    ' HDMI display test for early P2 silicon with 20MHz crystal and
    ' P[7:0] connected to HDMI {R+, R-, G+, G-, B+, B-, CLK+, CLK-}
    '
    ' The next version of silicon will have TMDS hardware to compose LVDS stream on the fly.
    '
    dat     org
    
            hubset  ##%1_000001_0000011000_1111_10_00   'enable crystal+PLL, stay in 20MHz+ mode
            waitx   ##20_000_000/100            'wait ~10ms for crystal+PLL to stabilize
            hubset  ##%1_000001_0000011000_1111_10_11   'now switch to PLL running at 250MHz
    
            setxfrq ##$80000000     'set streamer to output on every clock
    
            mov dira,#$FF       'P[7:0] = {R+, R-, G+, G-, B+, B-, CLK+, CLK-}
    '
    '
    ' Write visible line into hub
    '
    vline       wrfast  #0,line_vis     'ready to write line data
    
            mov bal_r,#0        'reset balance accumulators
            mov bal_g,#0
            mov bal_b,#0
    
            mov z,##640         'write visible pixels
    .prep       callpa  #0*256/3,#pretty
            setbyte rgb,pa,#3
            callpa  #1*256/3,#pretty
            setbyte rgb,pa,#2
            callpa  #2*256/3,#pretty
            setbyte rgb,pa,#1
            call    #convert_rgb
            djnz    z,#.prep
    
            mov z,#16           'write pre-hsync
    .hpre       mov color_r,sync0
            mov color_g,sync0
            mov color_b,sync0
            call    #output_rgb
            djnz    z,#.hpre
    
            mov z,#16           'write hsync
    .hsync      mov color_r,sync0
            mov color_g,sync0
            mov color_b,sync1
            call    #output_rgb
            djnz    z,#.hsync
    
            mov z,#128          'write post-sync
    .hpost      mov color_r,sync0
            mov color_g,sync0
            mov color_b,sync0
            call    #output_rgb
            djnz    z,#.hpost
    '
    '
    ' Write invisible line into hub
    '
    iline       mov z,##640+16
    .hpre       mov color_r,sync0
            mov color_g,sync0
            mov color_b,sync0
            call    #output_rgb
            djnz    z,#.hpre
    
            mov z,#16
    .hsync      mov color_r,sync0
            mov color_g,sync0
            mov color_b,sync1
            call    #output_rgb
            djnz    z,#.hsync
    
            mov z,#128
    .hpost      mov color_r,sync0
            mov color_g,sync0
            mov color_b,sync0
            call    #output_rgb
            djnz    z,#.hpost
    '
    '
    ' Write sync line into hub
    '
    sline       mov z,##640+16
    .hpre       mov color_r,sync0
            mov color_g,sync0
            mov color_b,sync2
            call    #output_rgb
            djnz    z,#.hpre
    
            mov z,#16
    .hsync      mov color_r,sync0
            mov color_g,sync0
            mov color_b,sync3
            call    #output_rgb
            djnz    z,#.hsync
    
            mov z,#128
    .hpost      mov color_r,sync0
            mov color_g,sync0
            mov color_b,sync2
            call    #output_rgb
            djnz    z,#.hpost
    '
    '
    ' Output screen data over and over
    '
            rdfast  line_cnt,line_vis   'ready to loop-read visible line buffer
    
    .field      mov x,#480          'ready for 480 visible lines
    .vis        xcont   line_mod,#3     'output visible line
            cmp x,#1        wz  'if last line, update fblock to invisisble line
        if_z    fblock  line_cnt,line_inv
            djnz    x,#.vis
    
            mov x,#10           'ready for 10 invisible lines
    .pre        xcont   line_mod,#3     'output visible line
            cmp x,#1        wz  'if last line, update fblock to sync line
        if_z    fblock  line_cnt,line_syn
            djnz    x,#.pre
    
            mov x,#2            'ready for 2 sync lines
    .sync       xcont   line_mod,#3     'output visible line
            cmp x,#1        wz  'if last line, update fblock to invisisble line
        if_z    fblock  line_cnt,line_inv
            djnz    x,#.sync
    
            mov x,#33           'ready for 33 invisible lines
    .post       xcont   line_mod,#3     'output visible line
            cmp x,#1        wz  'if last line, update fblock to visisble line
        if_z    fblock  line_cnt,line_vis
            djnz    x,#.post
    
            jmp #.field
    '
    '
    ' Make pretty color from pa and z into x
    '
    pretty      mov x,z
            sca x,##round(256.0/480.0 * float($10000))
            add pa,0
            shl pa,#24
            qrotate #127,pa
            getqx   pa
        _ret_   bitnot  pa,#7
    '
    '
    ' Data
    '
    sync0       long    %1101010100     '
    sync1       long    %0010101011     '    hsync
    sync2       long    %0101010100     'vsync
    sync3       long    %1010101011     'vsync + hsync
    
    line_mod    long    $1080<<16 + linebytes   'RFBYTE streamer mode
    line_cnt    long    linebytes / 64  
    
    line_vis    long    base + linebytes*0  'visible line address
    line_inv    long    base + linebytes*1  'invisible line address
    line_syn    long    base + linebytes*2  'sync line address
    '
    '
    ' Convert 8:8:8:0 RGB into 10-byte TMDS pattern in hub
    '
    convert_rgb getbyte color,rgb,#3
            mov bal,bal_r
            call    #color_tmds
            mov bal_r,bal
            mov color_r,color
    
            getbyte color,rgb,#2
            mov bal,bal_g
            call    #color_tmds
            mov bal_g,bal
            mov color_g,color
    
            getbyte color,rgb,#1
            mov bal,bal_b
            call    #color_tmds
            mov bal_b,bal
            mov color_b,color
    
    output_rgb  mov x,#0
    .loop       shr color_r,#1  wc
            bitc    y,#7
            bitnc   y,#6
            shr color_g,#1  wc
            bitc    y,#5
            bitnc   y,#4
            shr color_b,#1  wc
            bitc    y,#3
            bitnc   y,#2
            cmp x,#5        wc
            bitc    y,#1
            bitnc   y,#0
            wfbyte  y
            incmod  x,#9        wc
        if_nc   jmp #.loop
    
            ret
    '
    '
    ' Convert R/G/B in color[7:0] into TMDS in color[9:0]
    '
    color_tmds  ones    bal_m,color     'ones > 4 || ones == 4 && !color[0]?
            cmp bal_m,#4    wcz
        if_z    testb   color,#0    wc  'c=0 for XNOR
    
            testb   color,#0    wz
      if_z_eq_c bitnot  color,#1
        
            testb   color,#1    wz
      if_z_eq_c bitnot  color,#2
        
            testb   color,#2    wz
      if_z_eq_c bitnot  color,#3
        
            testb   color,#3    wz
      if_z_eq_c bitnot  color,#4
        
            testb   color,#4    wz
      if_z_eq_c bitnot  color,#5
        
            testb   color,#5    wz
      if_z_eq_c bitnot  color,#6
        
            testb   color,#6    wz
      if_z_eq_c bitnot  color,#7
    
            ones    bal_m,color     'get bal_m
    
            bitc    color,#8
    
            sub bal_m,#4    wcz 'sign of bal_m into c, (bal_m == 0) into z
    
        if_nz   cmp bal,#0      wz  'get (bal_m == 0 || bal == 0) into z
    
            testbn  bal,#31     xorc    'get (bal_m[31] == bal[31]) into c
            wrc bal_sign        'get (bal_m[31] == bal[31]) into bal_sign
    
        if_z    testbn  color,#8    wc  'inv_m = bal_zero ? !m[8] : bal_sign
    
            bitc    color,#9        'finalize TMDS pattern
        if_c    xor color,#$FF
    
            shl bal_m,#1        'adjust bal
    
            testbn  color,#8    wc  
        if_z    jmp #.sum
    
            testb   bal_sign,#0 wc
            testb   color,#8    wz
      if_c_eq_z sumnc   bal,#2
    .sum    _ret_   sumc    bal,bal_m
    '
    '
    ' Data
    '
    color       res 1
    bal     res 1
    bal_m       res 1
    bal_sign    res 1
    
    bal_r       res 1
    bal_g       res 1
    bal_b       res 1
    
    color_r     res 1
    color_g     res 1
    color_b     res 1
    
    rgb     res 1
    
    x       res 1
    y       res 1
    z       res 1
    t       res 1
    
    
    

    The DVI spec calls for the control bits on red and green to always be zero. In the code that is the sync0 word. It was sync2. Was there a reason for that or was it just overlooked because it worked on most monitors?
  • thanks Saucy, good find, i'll give that a try soon and report back
  • I don't really want to spend a lot of time on generating video signals in software since the next silicon revision will do it in hardware.

    Anyway, here is a program that outputs a grayscale image. It only produces 52 shades of gray instead of 256. That restriction makes it possible to just grab an output stream from the table and use it without worrying about the 1/0 balance of the resulting signal. I think it would work fine for a text display. They aren't evenly spaced, but 52 gray levels is way more than what the P1 did.

    If we had 3 cogs generating to generate the RGB channels independently we could have 140608 colors. If the streamer had an option to shift 3 bits at a time we could have a palette of these colors. We can generate 2 independent signals with 2 bit mode, then vary which 2 channels are linked by changing the LUT. There might not be enough time do this for every pixel. I do this to generate the sync on blue and blanking on red and green.
  • Thats grayscale is really neat, James.

    Still no luck with the TCL monitor, though it does seem to recognize a signal is there now (but doesn't display it), whereas I don't think it did this before.

    I noticed in your code you have a point where you get the phase shift of the clock aligned, but make a comment how 'curiously it doesn't seem to matter' - should I try some different values here and see whether it makes a difference?
  • Thanks!

    It may only want to support HDMI modes and not DVI modes. I have an old TV that has separate HDMI and DVI modes. Sometimes it only works on one of the settings. It will be a while before I can test that unit with the P2.

    You could try changing the clock phase. It should be "correct" already. 10 sysclocks is 1 output cycle. The code from VonSzarvas generates what I consider the correct phase. We might get it if we generate a 720x480 signal. An easy thing to try would be to use 270MHz sysclock. Also, are you in an NTSC or PAL region?
  • evanhevanh Posts: 15,126
    edited 2019-08-08 10:29
    Same for me. LCD TV gives the 6x grey roses and PC monitor gives out of range message.

    EDIT: Oops, I should have posted this reply on the other topic (not sure if it's the same program) - https://forums.parallax.com/discussion/comment/1475344/#Comment_1475344

  • samuellsamuell Posts: 554
    edited 2019-08-08 22:39
    The grayscale image is very nice. However, I tried to run the 720p test with the 6 images, but my TV doesn't even recognize that there is a signal, even when reconnecting the HDMI cable.

    Anyway, if you are interested to see the results of the 480p test, see the photo attached.

    Kind regards, Samuel Lourenço
    1024 x 768 - 91K
Sign In or Register to comment.