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

  • 14 Comments sorted by Date Added Votes
  • 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 January 28 Vote Up0Vote Down
    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
    David
    PropWare: C++ HAL (Hardware Abstraction Layer) for PropGCC; Robust build system using CMake; Integrated Simple Library, libpropeller, and libPropelleruino (Arduino port); Instructions for Eclipse and JetBrain's CLion; Example projects; Doxygen documentation
  • 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
    David
    PropWare: C++ HAL (Hardware Abstraction Layer) for PropGCC; Robust build system using CMake; Integrated Simple Library, libpropeller, and libPropelleruino (Arduino port); Instructions for Eclipse and JetBrain's CLion; Example projects; Doxygen documentation
  • 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
    “Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away. -Antoine de Saint-Exupery
  • 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"?
    David
    PropWare: C++ HAL (Hardware Abstraction Layer) for PropGCC; Robust build system using CMake; Integrated Simple Library, libpropeller, and libPropelleruino (Arduino port); Instructions for Eclipse and JetBrain's CLion; Example projects; Doxygen documentation
  • I suspect the OP is looking for a canned C/C++ wrapper around the necessary PASM code.

    -Phil
    “Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away. -Antoine de Saint-Exupery
  • 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))
    
    David
    PropWare: C++ HAL (Hardware Abstraction Layer) for PropGCC; Robust build system using CMake; Integrated Simple Library, libpropeller, and libPropelleruino (Arduino port); Instructions for Eclipse and JetBrain's CLion; Example projects; Doxygen documentation
  • That's a start. There are registers that require some setup before waitvid can be used.

    -Phil
    “Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away. -Antoine de Saint-Exupery
  • 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
    
    David
    PropWare: C++ HAL (Hardware Abstraction Layer) for PropGCC; Robust build system using CMake; Integrated Simple Library, libpropeller, and libPropelleruino (Arduino port); Instructions for Eclipse and JetBrain's CLion; Example projects; Doxygen documentation
  • yousefyousef Posts: 21
    edited January 30 Vote Up0Vote Down
    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.