Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 7 of 7

Thread: A set of scope-tested 100-500 ns delay macros

  1. #1

    A set of scope-tested 100-500 ns delay macros

    After some frustration with timing jitter from a short loop like that in delayMicroseconds, I put a set of hundred-nanosecond delay macros together today for bit-banging a second SPI port on my Teensy 3.2 and thought I'd share. Dedicated to the public domain.

    The sketch below is what I used to empirically determine the combinations of NOP3, NOP4, and NOP6 to use for each macro in each case. I tried to get them all to conform as closely as possible to a 100-500 ns negative pulse width, from a high setting to a low setting and then back high again, erring on the side of a pulse too long rather than too short. I kept my eye on the positive pulse width, too, though that was intermittently longer (perhaps up to 20%) due to the beginning of the sketch loop.

    You can stack these up to get longer delays, although I wouldn't be surprised if there was some non-linearity involved. And if your desired delays get long enough, you're just getting into the territory of delayMicroseconds.

    Of course, the delay of digitalWriteFast is inherently included in the delay of each macro. That's probably what you'd want this delay to be used with anyhow.

    I'm sure all the macro expansion bloats the compiled code somewhat, especially with longer delays, but I doubt if it adds up to much. Even with an F_CPU of 96MHz and a PAUSE of P5, I'm only seeing this sketch occupy 5% of program storage space.

    Code:
    // Empirically determined by Ed Suominen with an oscilloscope and a good deal of
    // pressing Ctrl+U in the Arduino window. No guarantees expressed or implied. Dedicated
    // to the public domain.
    
    #define pinNum 13
    void setup() {
      pinMode(pinNum, OUTPUT);
    }
    
    #define NOP3 "nop\n\t""nop\n\t""nop\n\t"
    #define NOP4 "nop\n\t""nop\n\t""nop\n\t""nop\n\t"
    #define NOP6 "nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"
    
    // P1-5 are 100-500 ns pauses, tested with an oscilloscope (2 second
    // display persistence) and a Teensy 3.2 compiling with
    // Teensyduino/Arduino 1.8.1, "faster" setting
    #if F_CPU == 96000000
    #define P1 __asm__(NOP4 NOP4)
    #define P2 __asm__(NOP6 NOP6 NOP6)
    #define P3 __asm__(NOP6 NOP6 NOP6 NOP6 NOP3)
    #define P4 __asm__(NOP6 NOP6 NOP6 NOP6 NOP6 NOP4 NOP4)
    #define P5 __asm__(NOP6 NOP6 NOP6 NOP6 NOP6 NOP6 NOP6 NOP4 NOP3)
    
    #elif F_CPU == 72000000
    #define P1 __asm__(NOP6)
    #define P2 __asm__(NOP6 NOP6)
    #define P3 __asm__(NOP6 NOP6 NOP6 NOP3)
    #define P4 __asm__(NOP6 NOP6 NOP6 NOP6 NOP4)
    #define P5 __asm__(NOP6 NOP6 NOP6 NOP6 NOP4 NOP4 NOP3)
    
    #elif F_CPU == 48000000
    #define P1 __asm__(NOP4)
    #define P2 __asm__(NOP6 NOP3)
    #define P3 __asm__(NOP6 NOP4 NOP3)
    #define P4 __asm__(NOP6 NOP6 NOP6)
    #define P5 __asm__(NOP6 NOP6 NOP4 NOP4 NOP3)
    
    #endif
    
    #define PAUSE P5
    
    void loop() {
      noInterrupts();
      digitalWriteFast(pinNum, HIGH); // 1
      PAUSE;
      digitalWriteFast(pinNum, LOW);
      PAUSE;
      digitalWriteFast(pinNum, HIGH); // 2
      PAUSE;
      digitalWriteFast(pinNum, LOW);
      PAUSE;
      digitalWriteFast(pinNum, HIGH); // 3
      PAUSE;
      digitalWriteFast(pinNum, LOW);
      PAUSE;
      interrupts();
    }
    Last edited by edsuom; 03-24-2017 at 02:09 AM.

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    15,720
    I've added a link to this thread, on this page.

    https://www.pjrc.com/teensy/td_timing_delay.html

    Hopefully it will help others to find these macros.

    Maybe in time others will be done for Teensy LC, 3.5, and 3.6 at their many clock speeds?

  3. #3
    Moderator Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    4,347
    One should mention that interrupts should be disabled if a maximum delay time is desired.

  4. #4
    Quote Originally Posted by Frank B View Post
    One should mention that interrupts should be disabled if a maximum delay time is desired.
    Not sure what you intended to say there. Interrupts will increase the delay time, so disabling them will result in minimum delay, not maximum.

  5. #5
    Moderator Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    4,347
    I think I intended to write "exact".. ;-) Anyway, this post is a couple of month old..

  6. #6
    Ah, exact makes sense. As to couple of months old -- yeah, but posts on here continue to be useful for years!

  7. #7
    Junior Member
    Join Date
    Sep 2017
    Posts
    3
    Hi, I'm using Teensy 3.6 with clock rate of 180 Mhz, what should be my setup for P1 to P5?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •