Shop OBEX P1 Docs P2 Docs Learn Events
PASM version of pinwrite(pinfield, data)? — Parallax Forums

PASM version of pinwrite(pinfield, data)?

Is there a simple way to set non-contiguous pin values within a pinfield in a single PASM2 instruction? I am trying to turn non-contiguous Smart Pins on/off in the same clock cycle with a drvh/drvl type of mechanism and am unable to come up with the right approach.

Comments

  • You can write directly into OUTA and OUTB registers to affect pin states.

    (pinwrite(base addpins ext), data)
    is roughly equivalent to this (minus port a/b handling)

    bmask ext
    rol ext,base
    rol data,base
    setq ext
    muxq outa,data
    

    Infact, the actual pinwrite implementation in the Spin2 Interpreter (y and w are the parameters):

    pinw_           ror     y,#6    wc      'y=pins, w=val (begins at pop2 in LUT)
                    bitc    pinw_reg,#9     'select outa/outb for writing
    
                    bmask   v,y             'make mask
                    rol     y,#6
    
                    rol     v,y             'justify mask
                    rol     w,y             'justify val
    
                    setq    v               'mux val into outa/outb using mask
    pinw_reg        muxq    outa,w
    
            _ret_   dirh    y               'enable outputs
    

    Of course if your pin numbers start on a multiple of 8, you might use SETBYTE instead of the longer SETQ/MUXQ approach. (same for SETIB/SETWORD).
    Or if you just want to toggle pin states, you can obviously just a XOR instruction.

  • Thank you for the response. This makes sense but I have a problem implementing...

    This code is intended to blink leds 56 and 59 (p_ext, p_base = 5, 24) but it doesn't. Am I close?

    dat
    
            org
    
    p_write mov dirb, ##$ff00_0000         
            bmask ext
            rol  ext, base
            getct ct1
    
    .loop   addct1 ct1, delay
            waitct1
    
            mov data, #1
            rol data, base
            setq ext
            muxq outb, data
    
            addct1 ct1, delay
            waitct1
    
            mov data, #4
            rol data, base
            setq ext
            muxq outb, data
            jmp #.loop
    
    ct1     res 1
    delay   long  297_000_000
    
    ext     long  p_ext
    base    long  p_base
    data    long  0
    
  • RES variables must always come after everything else, otherwise the addresses shift around and everything stops making sense.

  • Works like a champ; only the desired pinfield is modified. Thank you for the solution and for remedial PASM education.

  • I am having a problem understanding how this works. If I put the assembly code inline it works. If I put it in a cog it fails. Am I missing a fundamental consideration.

    This version works:

    PUB main()  | pins, data, mask
    
    
      pins := 56 addpins 4
      data := %10101
    
    
    org
    
    start   ror   pins, #6          wc
            bitc  led, #9
            bmask mask, pins
            rol   pins, #6
            rol   mask, pins
    
            dirh   pins
            rol    data, pins
    
    loop    setq   mask
    led     muxq   outa, data
            jmp    #loop
    
    
    end
    
    

    This version does not:

    VAR cogvar[8]
    
    
    PUB main()  | _pins, _data, _mask
    
    
      _pins := 56 addpins 4
      _data := %10101
    
      longmove(@cogvar, @_pins, 2)
    
      coginit(1, @start, @cogvar)
    
    DAT
    
    org
    
    start   setq #1
            rdlong pins, ptra
    
            ror   pins, #6          wc
            bitc  led, #9
            bmask mask, pins
            rol   pins, #6
            rol   mask, pins
    
            dirh   pins
            rol    data, pins
    
    loop    setq   mask
    led     muxq   outa, data
            jmp    #loop
    
    pins    res   1
    data    res   1
    mask    res   1
    
  • Normally, you want your main to not return while other tasks are still going, put an empty repeat block after coginit (or coginit over cog 0, if you really want). Not sure if that's it though.

  • If I use outb in the led register it works. Apparently the bitc led,#9 instruction isn't modifying the register.

  • That would normally indicate missing ORG, but it seems to be there (i usually prefer explicit ORG 0 but it shouldn't matter. Or does it? Am confused on this one, too.).

  • I am confused too but now I have a version that works... sometimes I think I am losing my mind!

    CON
      _clkfreq = 297_000_000                'set clock frequency
    
      delay = 297_000_000
    
    
    VAR cogvar[8]
    
    
    PUB main()  | _pins, _data, _mask
    
    
      _pins := 56 addpins 4
      _data := %10101
    
      longmove(@cogvar, @_pins, 2)
    
      coginit(1, @start, @cogvar)
      waitms(10)
      repeat
       cogvar[1] += 1
       waitms(50)
    
    DAT
    
    org
    
    start   setq #1
            rdlong pins, ptra
            add ptra, #4
    
            ror   pins, #6          wc
            bitc  led, #9
            bmask mask, pins
            rol   pins, #6
            rol   mask, pins
    
            dirh   pins
    
    loop    rdlong data, ptra
            rol    data, pins
            setq   mask
    led     muxq   outa, data
    
            jmp    #loop
    
    pins    res   1
    data    res   1
    mask    res   1
    
    
Sign In or Register to comment.