Shop OBEX P1 Docs P2 Docs Learn Events
Drawing line to LCD, help understanding fix — Parallax Forums

Drawing line to LCD, help understanding fix

Hello All!
I have written the below code to write a line to an LCD screen(R61581 controller/16 bit interface), and it only works if I enter 4 nop's before the pixel loop(it also works with them in other parts of the code, but this is just one fix). Can anyone tell my why this fixes it? It is not a delay issue, as I have tried to enter a waitcnt loop instead, and it still does not work. For reference, exactly what I am seeing is that without the nop's the wrdt variable somehow ends up getting cleared to zero between the call to wrbus, and getting to wrbus. I have validated this via debugging. I have put a string of #'s by the NOPs for easy location. Any suggestions or answers as to why this fixes it?



:wrline
                        'ReadData
                        mov line, #1
                        rdlong r1, cloc                 'Get XO
                        rdlong r2, bcloc                'Get Y0
                        rdlong r3, xloc                 'Get X1                          
                        rdlong r4, yloc                 'Get Y1
                        rdlong dt, datloc               'Get Color

                        'r8=steep
                        'r9=dx
                        'r10=dy
                        'r11=err
                        
                        mov r8, #0
                        
                        mov r6, r3                      'Get || x1-x0
                        sub r6, r1
                        abs r7, r6

                        mov r6, r4                      'Get || y1-y0    
                        sub r6, r2
                        abs r5, r6
                        
                        cmp r7, r5              wc          
              if_c      mov r8, #1                      'Write steep as 1 if  ||y1-y0 > ||x1-x0, else steep is 0      

                        'If steep, then switch x0, y0, and switch x1, y1
              if_c      mov r6, r2
              if_c      mov r2, r1
              if_c      mov r1, r6

              if_c      mov r6, r3
              if_c      mov r3, r4
              if_c      mov r4, r6

                        
              
                        'If x0>x1, then swap x0,x1, and swap y0,y1

                        cmp r3, r1              wc
                        
              if_c      mov r6, r3
              if_c      mov r3, r1
              if_c      mov r1, r6

              if_c      mov r6, r2
              if_c      mov r2, r4
              if_c      mov r4, r6


                        'r8=steep
                        'r9=dx
                        'r10=dy
                        'r11=err
                        'r12=ystep

                        mov r9, r3                      'Calcluate DX = x1-x0
                        sub r9, r1

                        mov r5, r4                      'Calculate DY = ||y1-y0
                        sub r5, r2
                        abs r10, r5

                        mov r11, r9                     'Calculate err = dx / 2
                        shr r11, #1

                        'If y0 < y1
                        cmp r2, r4              wc      'Test if y0 < y1, if true ystep = 1, else ystep = -1
        if_c            mov r12, #1
        if_nc           mov r12, negate


These are the nops that fix the procedure
####################
                        nop
                        nop
                        nop
                        nop   
        
####################

:linepxloop
                        cmp r3, r1              wc      'If X1 < X0, stop loop
        if_c            mov line, #0    
        if_c            jmp #:loopreturn
                        call #drawlinepixel
                        subs r11, r10                    'err = err - dy
                        cmps r11, #0            wc      'Test if err < 0
        if_c            add r2, r12                     'If so, add ystep
        if_c            adds r11, r9                     'and add dx to err
                        add r1, #1                      'Increment x0
                        jmp #:linepxloop                'Continue linepxloop 



drawlinepixel
                        cmp r8, #1              wz      'Test if steep is 1, if so draw pixel at x0,y0
        if_z            mov yp, r1
        if_z            mov xp, r2
        if_nz           mov xp, r1                       'Else draw pixel at Y0,X0
        if_nz           mov yp, r2
                        call #setxypixel
                        andn outa, dcmask
                        mov wrdt,#$2C
                        call #wrbus
                        or outa, dcmask
                        mov wrdt, dt
                        call #wrbus
                         
drawlinepixel_ret       ret


setxypixel
                        'reg xp and yp must be correct

                        
                        
                        'Send command 2A
                        andn outa, dcmask 
                        mov wrdt, #$2A
                        call #wrbus
                        or outa, dcmask

                        'Send Y0
                        mov wrdt, yp
                        shr wrdt, #8
                        call #wrbus
                        
                        mov wrdt, yp
                        and wrdt, $FF
                        call #wrbus

                        add yp, #1

                        'Send Y1
                        mov wrdt, yp
                        shr wrdt, #8
                        call #wrbus

                        mov wrdt, yp
                        and wrdt, $FF
                        call #wrbus

                        

                        'Send command 2B
                        andn outa, dcmask  
                        mov wrdt, #$2B
                        call #wrbus
                        or outa, dcmask

                        'Send X0
                        mov wrdt, xp
                        shr wrdt, #8 
                        call #wrbus

                        mov wrdt, xp
                        and wrdt, $FF
                        call #wrbus

                        add xp, #1
                        
                        'Send X1
                        mov wrdt, xp
                        shr wrdt, #8 
                        call #wrbus

                        mov wrdt, xp
                        and wrdt, $FF
                        call #wrbus
setxypixel_ret          ret


wrbus
                        andn outa, busmask      'Clear bus lines
                        or outa, wrdt           'Write data to output 
                        andn outa, wrmask
                        or outa, wrmask          
wrbus_ret               ret

Comments

  • ElectrodudeElectrodude Posts: 1,658
    edited 2015-10-30 01:04
    Can you add your cogram variable definitions (long, res, etc.) to your post?

    If you're using res, are all of your res statements after your code? If they're before, you'll have problems.
  • Ah, I figured it out finally, I was missing the # directive from some of the $FF masks for masking the xy pixel locations. The nops must have kicked the code down enough to have an $FF be at that location. Thanks for your reply!
  • For reference Here is the full code(partially complete mind you):
    org 0

    entry
    mov datloc, par
    mov wrtsloc, datloc
    add wrtsloc, #4
    mov flgloc, wrtsloc
    add flgloc, #4
    mov cloc,flgloc
    add cloc, #4
    mov bcloc, cloc
    add bcloc, #4
    mov xloc, bcloc
    add xloc, #4
    mov yloc, xloc
    add yloc, #4

    rdlong debugxloc, bcloc
    rdlong debugyloc, xloc

    'Setup data bus
    or dira, busmask

    'Setup WRPIN
    rdlong wrpin, datloc 'Read wrpin
    mov wrmask, #1 'Get wrpin mask
    shl wrmask, wrpin
    or outa, wrmask 'Write pin idle at high
    or dira, wrmask 'Set pin directions

    'Setup DCPIN
    rdlong dcmask, wrtsloc 'Read dc pin mask
    or dira, dcmask 'Set pin direction

    'Setup CSPIN
    rdlong csmask, cloc 'Read cs pin mask
    or outa, csmask 'Set CS idle high
    or dira, csmask 'Set pin direction


    'Set Counter A for wrpin clock
    mov ctra, wrpin 'Set counter A data pin
    movi ctra,#%0_00100_000

    '
    :loopreturn
    or outa, csmask 'Deselect Chip
    wrlong null, flgloc 'Clear datatype flag

    :loop
    rdlong r1, flgloc 'Get function flag
    tjz r1, #:loop
    rdlong wrdt, datloc 'Get data\data location from location
    rdlong wrts, wrtsloc 'Get writes to perform
    andn outa, csmask 'Select Chip
    cmp r1, #1 wz 'Test if continuous write
    if_z jmp #:writecont
    cmp r1, #2 wz 'Test if write from location
    if_z jmp #:writeloc
    cmp r1, #3 wz 'Test if write slow
    if_z jmp #:wrsingle
    cmp r1, #5 wz 'Test if write line
    if_z jmp #:wrline
    cmp r1, #6 wz 'Test if write char
    if_z jmp #:writechar
    cmp r1, #7 wz 'Test if set font
    if_z jmp #:setfont
    jmp #:loop




    :wrsingle
    rdlong r1, wrtsloc 'Get datatype
    cmp r1, #0 wz 'Test datatype
    if_z andn outa, dcmask 'If zero, clear dc pin
    if_nz or outa, dcmask 'If not zero, set dc pin
    call #wrbus
    jmp #:loopreturn



    :writecont
    andn outa, busmask
    or outa, wrdt
    or outa, dcmask
    mov phsa,#0
    andn outa, wrmask 'Allow control of wrpin from counters
    movi frqa,#%001000000 'Start counting at 10MHz
    :writecloop
    nop
    djnz wrts, #:writecloop 'If not end of writes, continue
    mov frqa, #0 'Stop Counting
    mov phsa,#0
    or outa, wrmask 'Set wrpin high again.
    jmp #:loopreturn



    :writeloc
    rdword r1, wrdt 'Read word of data from location
    or outa, r1 'Set bus line
    andn outa, wrmask 'Set wrpin low
    or outa, wrmask 'Set wrpin high
    add wrdt, #2 'Jump to next word of data
    andn outa, busmask 'Clear data lines
    djnz wrts, #:writeloc 'If not end of writes, continue
    jmp #:loopreturn






    :writechar
    rdlong xp, xloc 'Get x
    rdlong yp, yloc 'Get y

    or outa, dcmask 'Set DC for data


    'Calculate char address
    mov r1, wrdt
    sub r1, foffset
    mov r2, fxsize
    shr r2, #3 'Divide by 8




    'Mult by fysize loc := ((char - foffset) * ((fxsize /8) * fysize))
    mov r5,#0
    mov r4, fysize
    :multloop
    shr r2,#1 wc
    if_c add r5,r4
    shl r4,#1
    tjnz r2,#:multloop

    'Move r5 into r6 for use as loop endpoint
    mov r6, r5

    'Mult by two sides (charloc = x * y)
    mov chloc,#0
    :multlooptwo
    shr r5,#1 wc
    if_c add chloc,r1
    shl r1,#1
    tjnz r5,#:multlooptwo


    'chloc now holds char location
    add chloc, floc

    rdlong r4, cloc 'Get color
    rdlong r5, bcloc 'Get BG color

    'Now join main loop for retreiving byte locations
    :charbyteloop
    'Get byte of pixel data
    rdbyte chr, chloc
    mov r2, #8 'subindex
    mov r3, chrmask 'r3 will be used to mask pixel data

    :charpixloop
    and chr, r3 nr, wz 'Test pixel data
    if_z mov wrdt, r5 'If zero, then write background color
    if_nz mov wrdt, r4 'If not zero, then write foreground color
    call #wrbus
    shr r3, #1 'Shift mask to the right
    djnz r2, #:charpixloop
    add chloc, #1 'Jump to next byte
    djnz r6, #:charbyteloop
    jmp #:loopreturn




    {
    ############ Set font for charachters ##############
    }

    :setfont
    mov floc, wrdt 'Get font location
    rdbyte fxsize, floc 'Get fxsize
    add floc, #1
    rdbyte fysize, floc 'Get fysize
    add floc, #1
    rdbyte foffset,floc
    add floc,#2
    jmp #:loopreturn













    :wrline
    'ReadData
    mov line, #1
    rdlong r1, cloc 'Get XO
    rdlong r2, bcloc 'Get Y0
    rdlong r3, xloc 'Get X1
    rdlong r4, yloc 'Get Y1
    rdlong dt, datloc 'Get Color

    'r8=steep
    'r9=dx
    'r10=dy
    'r11=err

    mov r8, #0

    mov r6, r3 'Get || x1-x0
    sub r6, r1
    abs r7, r6

    mov r6, r4 'Get || y1-y0
    sub r6, r2
    abs r5, r6

    cmp r7, r5 wc
    if_c mov r8, #1 'Write steep as 1 if ||y1-y0 > ||x1-x0, else steep is 0

    'If steep, then switch x0, y0, and switch x1, y1
    if_c mov r6, r2
    if_c mov r2, r1
    if_c mov r1, r6

    if_c mov r6, r3
    if_c mov r3, r4
    if_c mov r4, r6



    'If x0>x1, then swap x0,x1, and swap y0,y1

    cmp r3, r1 wc

    if_c mov r6, r3
    if_c mov r3, r1
    if_c mov r1, r6

    if_c mov r6, r2
    if_c mov r2, r4
    if_c mov r4, r6


    'r8=steep
    'r9=dx
    'r10=dy
    'r11=err
    'r12=ystep

    mov r9, r3 'Calcluate DX = x1-x0
    sub r9, r1

    mov r5, r4 'Calculate DY = ||y1-y0
    sub r5, r2
    abs r10, r5

    mov r11, r9 'Calculate err = dx / 2
    shr r11, #1

    'If y0 < y1
    cmp r2, r4 wc 'Test if y0 < y1, if true ystep = 1, else ystep = -1
    if_c mov r12, #1
    if_nc mov r12, negate


    :linepxloop
    cmp r3, r1 wc 'If X1 < X0, stop loop
    if_c mov line, #0
    if_c jmp #:loopreturn
    call #drawlinepixel
    subs r11, r10 'err = err - dy
    cmps r11, #0 wc 'Test if err < 0
    if_c add r2, r12 'If so, add ystep
    if_c adds r11, r9 'and add dx to err
    add r1, #1 'Increment x0
    jmp #:linepxloop 'Continue linepxloop



    drawlinepixel
    cmp r8, #1 wz 'Test if steep is 1, if so draw pixel at x0,y0
    if_z mov yp, r1
    if_z mov xp, r2
    if_nz mov xp, r1 'Else draw pixel at Y0,X0
    if_nz mov yp, r2
    call #setxypixel
    andn outa, dcmask
    mov wrdt,#$2C
    call #wrbus
    or outa, dcmask
    mov wrdt, dt
    call #wrbus

    drawlinepixel_ret ret


    setxypixel
    'reg xp and yp must be correct



    'Send command 2A
    andn outa, dcmask
    mov wrdt, #$2A
    call #wrbus
    or outa, dcmask

    'Send Y0
    mov wrdt, yp
    shr wrdt, #8
    call #wrbus

    mov wrdt, yp
    and wrdt, #$FF
    call #wrbus

    'Send Y1
    mov wrdt, yp
    shr wrdt, #8
    call #wrbus

    mov wrdt, yp
    and wrdt, #$FF
    call #wrbus



    'Send command 2B
    andn outa, dcmask
    mov wrdt, #$2B
    call #wrbus
    or outa, dcmask

    'Send X0
    mov wrdt, xp
    shr wrdt, #8
    call #wrbus

    mov wrdt, xp
    and wrdt, #$FF
    call #wrbus

    'Send X1
    mov wrdt, xp
    shr wrdt, #8
    call #wrbus

    mov wrdt, xp
    and wrdt, #$FF
    call #wrbus
    setxypixel_ret ret


    wrbus
    andn outa, busmask 'Clear bus lines
    or outa, wrdt 'Write data to output
    andn outa, wrmask
    or outa, wrmask
    wrbus_ret ret



    wait LONG 3000
    negate LONG -1
    null LONG 0
    busmask LONG $0000_FFFF
    chrmask BYTE %1000_0000


    datloc res 1 'Data pointer
    wrtsloc res 1 'Repeat Times location
    flgloc res 1 'flag pointer
    cloc res 1
    bcloc res 1
    xloc res 1
    yloc res 1

    wrpin res 1 'Write pin
    wrmask res 1 'Write pin mask
    csmask res 1 'CS pin mask
    dcmask res 1 'DC pin mask


    dt res 1 'Data to write read from hub
    r1 res 1
    r2 res 1
    r3 res 1
    r4 res 1
    r5 res 1
    r6 res 1
    r7 res 1
    r8 res 1
    r9 res 1
    r10 res 1
    r11 res 1
    r12 res 1

    wrdt res 1 'Data/data location to write

    line res 1

    debugxloc res 1
    debugyloc res 1

    xp res 1
    yp res 1

    wrts res 1 'Repeat times




    FIT 496

    [/code]
Sign In or Register to comment.