Shop OBEX P1 Docs P2 Docs Learn Events
P2 PASM %00100: Pulse/cycle output — Parallax Forums

P2 PASM %00100: Pulse/cycle output

If I understand the documentary correctly, this example makes exactly 1 positive pulse.

dat
    org 0
    dirl #20 ''Setup Smart Pin at P20
    wrpin PulseConfig, #20  ''Set config for pulse/cycle
    wxpin PulseTiming, #20 ' 'Set cycle time and logic-0' period
    dirh #20  ''Finished setup
    wypin Cycles, ''Pulse count to Y register
    nop ''Delay two clocks for IN to drop
.myloop
    jmp #.myloop ''Program waits forever

PulseConfig long %0000_0000_000_00000_00000000_11_00100_0 ''Pulse/cycle mode
Cycles long $0010 ''Pulse count of 16
PulseTiming long $01F4_05DC   ''60 usec pulse, 20 usec logic-0

According to the documentation I can also reverse the polarity.

To put out logic-0 pulses, replace the dirl instruction with dirh and change the
PulseConfig Mode value P5 bit to a 1:
%0000_0000_000_00000_00100000_11_00100_0

The code should then look like this.

dat
    org 0
    dirl #20 ''Setup Smart Pin at P20
    wrpin PulseConfig, #20  ''Set config for pulse/cycle
    wxpin PulseTiming, #20 ' 'Set cycle time and logic-0' period
    dirl #20  ''Finished setup +++++
    wypin Cycles, ''Pulse count to Y register
    nop ''Delay two clocks for IN to drop
.myloop
    jmp #.myloop ''Program waits forever

PulseConfig long %0000_0000_000_00000_00100000_11_00100_0 ''Pulse/cycle mode +++++
Cycles long $0010 ''Pulse count of 16
PulseTiming long $01F4_05DC   ''60 usec pulse, 20 usec logic-0
  1. I want to start several smartpins %00100: pulse/cycle at the same time.
    But the pins have different drvl/drvh .
    Is there a way to do this with one command?

  2. I assume the command "wypin cycl, #20" triggers the period delayed by 2 clk.

  3. How can I interrupt a single pulse generation during output.

Comments

  • evanhevanh Posts: 15,126

    @pic18f2550 said:
    If I understand the documentary correctly, this example makes exactly 1 positive pulse.

    Cycle is 16, therefore 16 pulses.

    According to the documentation I can also reverse the polarity.

    To put out logic-0 pulses, replace the dirl instruction with dirh and change the
    PulseConfig Mode value P5 bit to a 1:
    %0000_0000_000_00000_00100000_11_00100_0
    

    P6 - %0000_0000_000_0000001000000_00_00000_0 P_INVERT_OUTPUT

    The code should then look like this.
    ```
    dat
    org 0
    dirl #20 ''Setup Smart Pin at P20
    wrpin PulseConfig, #20 ''Set config for pulse/cycle
    wxpin PulseTiming, #20 ' 'Set cycle time and logic-0' period
    dirl #20 ''Finished setup +++++

    DIRH enables the smartpin, not DIRL

    1. I want to start several smartpins %00100: pulse/cycle at the same time.
    CON
      pins = 20 addpins 3   ' group of four pins,  P[23:20].
    

    Then replace #20 with "pins".

    1. I assume the command "wypin cycl, #20" triggers the period delayed by 2 clk.

    Not quite, it's one sysclock tick plus the remainder of running pulse period. The smartpin starts its period cycle when DIR goes high. Therefore the DIRH is the reference point in time.

    1. How can I interrupt a single pulse generation during output.

    DIRL instruction will shutdown any smartpin cycle.

  • evanhevanh Posts: 15,126
    edited 2021-06-18 04:35

    @evanh said:

    @pic18f2550 said:

    dat
        org 0
        dirl #20 ''Setup Smart Pin at P20
        wrpin PulseConfig, #20  ''Set config for pulse/cycle
        wxpin PulseTiming, #20 ' 'Set cycle time and logic-0' period
        dirl #20  ''Finished setup +++++
    

    DIRH enables the smartpin, not DIRL

    What I mean there is the second DIRL is wrong. There is no finish of setup. There is only smartpin enable/go - which is DIR going high.

    Eg:

    con
        pins = 20 addpins 3  ''Pin group P[23:20]
    dat
        org 0
        dirl #pins ''Hold the pins/smartpins disabled while setting up the four smartpins, P[23:20]
        wrpin PulseConfig, #pins  ''Set smartpin mode to pulse/cycle
        wxpin PulseTiming, #pins ' 'Set cycle time (period) and pulse length
        dirh #pins  ''Enable the four smartpin group.  Cycle period starts cycling from here!
        ...
    

    EDIT: Fixed syntax error.

  • pic18f2550pic18f2550 Posts: 392
    edited 2021-06-18 14:15

    Ok "dirl" resets logic for smartpinn.
    Which level is now at the output, or is it set to input?

    What happens if now a "dirh" comes without wrpin, wxpin and wypin?

    I want to hold a single pin low from the group.
    Is a "wrpin #0, #pin" enough?

  • evanhevanh Posts: 15,126
    edited 2021-06-18 14:35

    @pic18f2550 said:
    Is a "wrpin #0, #pin" enough?

    Yep, that instantly changes the pin back to normal.

  • evanhevanh Posts: 15,126
    edited 2021-06-18 14:52

    @pic18f2550 said:
    Which level is now at the output, or is it set to input?

    That smartpin mode overrides pin output. There is a number of such modes. OUT stops working for the duration of those modes.

    IN is always fed by smartpin event status for all smartpin modes. IN returns to normal only when smartpin is off, ie: WRPIN #0, #pin.

    Signal flow is shown here - https://forums.parallax.com/discussion/comment/1519371/#Comment_1519371 I've labelled the smartpin's output SmartOut. And when the smartpin is off then SmartA passes through to IN.

  • OK so if I issue "WRPIN #0, #pin" it goes back to its old state.

    That is, if the pin was an input before, it now becomes one again.

  • evanhevanh Posts: 15,126

    Yup. :)

    Although, it should be pointed out that an output is still an input at the same time. DIR controls output enable, it doesn't stop the pin being an input.

  • evanhevanh Posts: 15,126
    edited 2021-06-18 20:58

    Oh, another small detail: Each pin is independent and indefinitely remembers its own WRPIN mode. So, for example, one cog can set it up and another cog can use it in that mode. A hard reset of the whole chip is the only wired mode reset to #0.

  • pic18f2550pic18f2550 Posts: 392
    edited 2021-06-21 09:20

    Hello,

    If I have understood everything correctly, the code below should cyclically output two pulses.
    One with pulse/pause deffinition and one with pause/pulse deffinition.

    CON
    
      MP_AH = 0
      MP_AL = 1
    
    PUB main()
    
      coginit(COGEXEC_NEW, @go, 0)
    
    DAT
            org     0
    go
            dirl    #MP_AH
            dirl    #MP_AL
            jmp     #jmp1
    loop
            waitse1                              ''wait for new period
    jmp1    setse1  #%001<<6 + MP_AH
    
            wrpin   pconfp, #MP_AH               ''Set config for pulse/cycle
            wxpin   w1, #MP_AH                   ''Set cycle time and logic-1 period
            wypin   cycl, #MP_AH
            dirh    #MP_AH                       ''Finished setup
    
            waitse1                              ''wait for new period
            setse1  #%001<<6 + MP_AL
    
            wrpin   pconfn, #MP_AL               ''Set config for pulse/cycle
            wxpin   w2, #MP_AL                   ''Set cycle time and logic-0 period
            wypin   cycl, #MP_AL
            dirh    #MP_AL                       ''Finished setup
    
            jmp     #loop
    
    pconfp  long  %0000_0000_000_00000_00000000_11_00100_0  ''logic-1 puls
    pconfn  long  %0000_0000_000_00000_00100000_11_00100_0  ''logic-0 puls
    cycl    long  1                                         ''generiert genau 1 puls
                                    ''    ____
    w1      long  $00FF_02FF        '' ..|    |________....
                                    ''             ____
    w2      long  $00FF_02FF        '' ..|________|    ....
                                    ''   <----$2FF---->
                                    ''   <$FF>    <$FF>
    
    
  • evanhevanh Posts: 15,126
    edited 2021-06-21 11:35

    Repeated DIRHs do nothing without intervening DIRLs. Sometimes no need to control DIR for a smartpin adjustment, but if you do then use both DIRL and DIRH.
    First event never occurs because Y is held at zero while DIR is low, ie: The WYPIN doesn't work. Nothing happens as a result!
    You've also still got the mistake in the inverted pin mode that I pointed out earlier.

    I've corrected the ASCII timing graph (w1 was wrong):

                                    ''    ________
    w1      long  $00FF_02FF        '' ..|        |____....
                                    ''             ____
    w2      long  $00FF_02FF        '' ..|________|    ....
                                    ''   <----$2FF---->
                                    ''   <$200>   <$FF>
    

    The lack of reference timing makes it really hard to see that timing on a scope.

    Attached is a rewritten working version with extra reference timing pin for scope trigger.
    EDIT: Small change made to attached program.

  • These are two pulse generators in cascade.
    In the 1st pulse generator the Y value of the 2nd is not set, because it is not needed and only dirh of the 1st is set.
    In the 2nd one it is the other way round.

    Dirl is always set because later it is not known where the chain begins and where it ends.
    It is about the triggering of different impulse pattern chains with different lengths.
    Here I only want to clarify how I get that with the cascading hinn.

    Small question about the addpins.
    in the smartpin documentation it says "DRVH #10 ADDPINS 7 ''Drive P10..P17 high".
    I read that as start with pin 10 and set the next 7 pins high.
    Or do I understand this wrong?

  • evanhevanh Posts: 15,126

    Fixed your timing diagram:

                                    ''    ________
    w1      long  $00FF_02FF        '' ..|        |____|....
                                    ''   <----$2FF---->.
                                    ''   <-$200--><$FF>.
                                    ''                 .         ____
    w2      long  $00FF_02FF        ''               ..|________|    |....
                                    ''                 <----$2FF---->
                                    ''                 <-$200--><$FF>
    
  • evanhevanh Posts: 15,126
    edited 2021-06-22 05:33

    @pic18f2550 said:
    in the smartpin documentation it says "DRVH #10 ADDPINS 7 ''Drive P10..P17 high".
    I read that as start with pin 10 and set the next 7 pins high.

    Correct.

    It encodes both parts in a single number. The base pin part goes in the lower 6 bits [5:0], and the ADDPIN part goes in the next higher 5 bits [10:6]. There is a group of prop2 instructions, and use that very encoding, that perform multi-pin operations in a single instruction time.

  • According to Doku, this should be true. :(

  • evanhevanh Posts: 15,126

    Yep.

    And a small detail: With some testing, I've worked out it takes 8 sysclock ticks for the smallest latency WYPIN response to an IN rising. Other testing says it takes 1 extra tick above instruction execution (2 ticks) for a smartpin to act. Therefore the cog sees IN at something like 5 ticks after smartpin finish. Some of that will be cog pipeline effect but some must also be smartpin finish-to-IN latency too I think.

  • evanhevanh Posts: 15,126

    Here's a demo that avoids the tiny 8 ticks latency by staggering the start times of the two smartpins:

    CON
        _clkfreq = 20_000_000
        MP_AH = 9
        MP_AL = 11
    
    DAT
        org 0
        asmclk
    
        dirl    #MP_AH
        dirl    #MP_AL
        wrpin   pconfp, #MP_AH
        wrpin   pconfn, #MP_AL
        wxpin   w1, #MP_AH          'set the pulse period
        wxpin   w2, #MP_AL          'set the pulse period
    
        setse1  #%001_000000 | MP_AH        'pin rise event
        setse2  #%001_000000 | MP_AL        'pin rise event
        pollse1                 'clear excess pending event
        pollse2                 'clear excess pending event
    
        mov pa, w1
        zerox   pa, #15             'remove ADDPINS part
        sub pa, #6              'compensate for instruction execution time
    
        dirh    #MP_AH              'begin first pulse period of first smartpin
        wypin   cycl, #MP_AH            'load pulses - pulses start from next pulse period
    
        waitx   pa              'delay the second smartpin by exactly one whole pulse period
        dirh    #MP_AL              'begin first pulse period of second smartpin
    
    loop
        wypin   cycl, #MP_AL            'load pulses - pulses start from next pulse period
        waitse1
        wypin   cycl, #MP_AH            'load pulses - pulses start from next pulse period
        waitse2
        jmp #loop
    
    
    
    'pconfp long    %0000_0000_000_0000000000000_11_00100_0  ''logic-1 puls
    'pconfn long    %0000_0000_000_0000001000000_11_00100_0  ''logic-0 puls
    pconfp  long    P_PULSE | P_OE
    pconfn  long    P_PULSE | P_OE | P_INVERT_OUTPUT
    cycl    long    1
                                    ''    ________
    w1      long  $00FF_02FF        '' ..|        |____....
                                    ''             ____
    w2      long  $00FF_02FF        '' ..|________|    ....
                                    ''   <----$2FF---->
                                    ''   <$200>   <$FF>
    
  • evanhevanh Posts: 15,126

    It works by alternating each smartpin WYPIN command and therefore skipping every other pulse period for both smartpins.

  • pic18f2550pic18f2550 Posts: 392
    edited 2021-06-22 13:59

    What happens when X[31:16] = 0? Does this correspond to $10000?

    What happens if X[31:16] = X[15:0] or X=0?

  • evanhevanh Posts: 15,126

    X[31:16] = 0 makes output stay high 100%. That's documented.

    X[15:0] = 0 isn't documented and seems to be $10000 effective.

  • Ok.
    If X[31:16] = 0, we can say that X[15:0] contains the active pulse duration.

    Too bad that there is no prescaler.
    the P2 (256Mhz) must be downstacked to generate low frequency pulses (below 3.9kHz).

    Or is there another solution?

  • evanhevanh Posts: 15,126

    Wow, how long? If you specify Y > 1 with X[31:16] = 0 then you'll get a longer single pulse. It should become Y * X[15:0] sysclock ticks.

  • evanhevanh Posts: 15,126
    edited 2021-06-29 10:37

    Yeah, that works well. If X = 1 then pulse length is Y ticks.

  • evanhevanh Posts: 15,126
    edited 2021-06-29 10:47

    Whoa! Y is a direct active register in that smartpin mode. Which means any programmed change to Y has instant effect.

  • @evanh said:
    Whoa! Y is a direct active register in that smartpin mode. Which means any programmed change to Y has instant effect.

    In what context?

    Does the new value immediately start the counting process?
    Like a WATCHDOG mode?

    I don't suppose that has any influence on the code structure.
    The counter should still wait until dirh is set.

    Oh, that's even a 48Bit timer now. :)

  • evanhevanh Posts: 15,126
    edited 2021-06-29 19:08

    @pic18f2550 said:

    @evanh said:
    Whoa! Y is a direct active register in that smartpin mode. Which means any programmed change to Y has instant effect.

    In what context?

    Caveat: X must equal 1 for it to always be instant. Otherwise the base period takes control.

    Does the new value immediately start the counting process?
    Like a WATCHDOG mode?

    You can update it during the countdown to lengthen or shorten. Even a value of 1 works.

    I don't suppose that has any influence on the code structure.
    The counter should still wait until dirh is set.

    Correct.

    Oh, that's even a 48Bit timer now. :)

    Yep. Although, when X > 1, the response time of changes to Y is no longer perfectly in sync with program.

Sign In or Register to comment.