Shop OBEX P1 Docs P2 Docs Learn Events
Propeller C double pulses — Parallax Forums

Propeller C double pulses

Hi everyone,
I am trying to use the propeller to generate two very short pulses using C language for research purposes. I want to control each pulse timing and the time between them. The time has to be in nanoseconds (i.e. 100 ns).
Using pulse_out I was able to get a pulse width of 12.5 ns which is very good. The problem is with the 2nd pulse. writing two pulse_out commands won't do the job. I can control the timing of the first and 2nd pulses, but I am not able to control the time in between the two. Writing:
set_io_dt(1);
pulse_out(0,1);
pulse_out(0,1);

would give me two pulses of 12.5 ns with a huge 100 us in between.
is there another way to implement this? I can do this in PASM, but I want to use C language.

Thanks

Comments

  • Try compiling in LMM mode instead of CMM. I believe CMM is the default, but it's quite slow. Compiling as LMM is larger, but much faster.
  • yousefyousef Posts: 21
    edited 2017-01-28 03:15
    JasonDorie wrote: »
    Try compiling in LMM mode instead of CMM. I believe CMM is the default, but it's quite slow. Compiling as LMM is larger, but much faster.

    It sure is faster, but not fast enough. it reduces from 100 us to 25 us.
  • yousef wrote: »
    Hi everyone,
    I am trying to use the propeller to generate two very short pulses using C language for research purposes. I want to control each pulse timing and the time between them. The time has to be in nanoseconds (i.e. 100 ns).
    Using pulse_out I was able to get a pulse width of 12.5 ns which is very good. The problem is with the 2nd pulse. writing two pulse_out commands won't do the job. I can control the timing of the first and 2nd pulses, but I am not able to control the time in between the two. Writing:
    set_io_dt(1);
    pulse_out(0,1);
    pulse_out(0,1);

    would give me two pulses of 12.5 ns with a huge 100 us in between.
    is there another way to implement this? I can do this in PASM, but I want to use C language.

    Thanks

    I would recommend you look into writing your timing critical code in one of the following methods:

    * C/C++ with the appropriate method(s) forced into fcache
    * Inline assembly with the assembly block forced into fcache
    * C/C++ compiled as "cogc", such that it is compiled to native PASM and executed in a dedicated cog
    * Raw PASM (PASM and GAS syntax are both supported by newer versions of PropGCC), running in a dedicated cog
  • My personal favorite is inline assembly forced into fcache. Here's an example in PropWare:

    https://github.com/parallaxinc/PropWare/blob/develop/PropWare/serial/uart/uarttx.h#L103
  • It's possible that the Pulse_out code has some overhead, but to get delays on the nanosecond scale you're pretty much stuck with PASM, however it's generated.

    1us on the Prop is 80 clock cycles, or 20 instructions. Interpreted code isn't likely going to be fast enough.
  • yousef wrote: »
    JasonDorie wrote: »
    Try compiling in LMM mode instead of CMM. I believe CMM is the default, but it's quite slow. Compiling as LMM is larger, but much faster.

    It sure is faster, but not fast enough. it reduces from 100 us to 25 us.
    You could try -mcog mode. It runs code natively with no interpretation. However, it is limited to very small programs that fit inside COG memory. You might write a drive using "COG C" and leave your main program using CMM or LMM.
  • The best way to get that kind of pulse control is to use the Prop's video circuitry. Are the video functions available from C/C++?

    -hil
  • The best way to get that kind of pulse control is to use the Prop's video circuitry. Are the video functions available from C/C++?

    -hil

    Everything is "available." But to be less pedantic, what exactly do you mean by that? Are you looking for C/C++ functions to wrap specific assembly instructions, like "waitcnt(a, b)" wraps "waitcnt a, b"?
  • I suspect the OP is looking for a canned C/C++ wrapper around the necessary PASM code.

    -Phil
  • I suspect the OP is looking for a canned C/C++ wrapper around the necessary PASM code.

    -Phil

    I've never actually used the video capabilities on the prop, so I don't know for sure, but is this what you're looking for? https://github.com/parallaxinc/propgcc/blob/5fc1abdabd91af35f92540696466b523333480b4/lib/include/propeller.h#L205
    /**
     * @brief Wait for video generator to accept pixel info
     *
     * @param colors A long containing four byte-sized color values, each describing the four possible colors of the pixel patterns in Pixels.
     * @param pixels The next 16-pixel by 2-bit (or 32-pixel by 1-bit) pixel pattern to display.
     */
    #define waitvid(colors, pixels) __builtin_propeller_waitvid((colors), (pixels))
    
  • That's a start. There are registers that require some setup before waitvid can be used.

    -Phil
  • That's a start. There are registers that require some setup before waitvid can be used.

    -Phil

    I'm surprised to see those registers are defined in a different header file... but oh well. :) they're there:
    /// Parameter register is used for sharing HUB RAM address info with the COG.
    #define PAR     _PAR
    /// The system clock count
    #define CNT     _CNT
    /// Use to read the pins when corresponding DIRA bits are 0.
    #define INA     _INA
    /// Unused in P8X32A
    #define INB     _INB
    /// Use to set output pin states when corresponding DIRA bits are 1.
    #define OUTA    _OUTA
    /// Unused in P8X32A
    #define OUTB    _OUTB
    /// Use to set pins to input (0) or output (1).
    #define DIRA    _DIRA
    /// Unused in P8X32A
    #define DIRB    _DIRB
    /// Counter A control register.
    #define CTRA    _CTRA
    /// Counter B control register.
    #define CTRB    _CTRB
    /// Counter A frequency register.
    #define FRQA    _FRQA
    /// Counter B frequency register.
    #define FRQB    _FRQB
    /// Counter A phase accumulation register.
    #define PHSA    _PHSA
    /// Counter B phase accumulation register.
    #define PHSB    _PHSB
    /// Video Configuration register can be used for other special output.
    #define VCFG    _VCFG
    /// Video Scale register for setting pixel and frame clocks.
    #define VSCL    _VSCL
    
  • yousefyousef Posts: 21
    edited 2017-01-30 02:00
    I will definitely try to use the counters or video generation to do the pulses. I wonder how the pulse_out function was implemented to achieve 12.5 ns time. The inline assembly results are not consistent. It is true I can achieve shorter delays, but I noticed that when I add or remove other commands from the code the time becomes different. for example:
    int main()
    {
    low(0);
    while(1)
    {
    __asm__(
    " mov outa,#0\n\t "
    " mov outa,#1\n\t"
    );
    }

    This results in a very fast switching. A delay of 50 ns is achieved between the pulses. However, writing:
    int main()
    {
    low(0);
    __asm__(
    " mov outa,#0\n\t "
    " mov outa,#1\n\t"
    " mov outa,#0\n\t "
    " mov outa,#1\n\t"
    " mov outa,#0\n\t "
    );
    }
    results in a time delay of 200 ns between the pulses. The only difference is the "While" loop. I don't know why this would affect the execution speed of the assembly instructions.

  • yousef wrote: »
    It is true I can achieve shorter delays, but I noticed that when I add or remove other commands from the code the time becomes different. for example:
    int main()
    {
    low(0);
    while(1)
    {
    __asm__(
    " mov outa,#0\n\t "
    " mov outa,#1\n\t"
    );
    }

    This results in a very fast switching. A delay of 50 ns is achieved between the pulses. However, writing:
    int main()
    {
    low(0);
    __asm__(
    " mov outa,#0\n\t "
    " mov outa,#1\n\t"
    " mov outa,#0\n\t "
    " mov outa,#1\n\t"
    " mov outa,#0\n\t "
    );
    }
    results in a time delay of 200 ns between the pulses. The only difference is the "While" loop. I don't know why this would affect the execution speed of the assembly instructions.

    Because the while loop is put into fcache that runs it at full cog speed (20 mips), while your "unrolled" loop executes at hubread speed (1/16 of the clock or 5 mips).
Sign In or Register to comment.