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

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
    18,651
    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
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    4,744
    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
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    4,744
    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?

  8. #8
    Junior Member
    Join Date
    Dec 2018
    Posts
    2
    Hi, what would be the __asm__ or NOP instructions for an Arduino UNO (F_CPU == 16000000)?

  9. #9
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    7,046
    Quote Originally Posted by brice3010 View Post
    Hi, what would be the __asm__ or NOP instructions for an Arduino UNO (F_CPU == 16000000)?
    Look for nop in this file :: ...\hardware\teensy\avr\cores\teensy\core_pins.h
    like >> asm volatile("nop\n");

  10. #10
    Junior Member
    Join Date
    Dec 2018
    Posts
    2
    Quote Originally Posted by defragster View Post
    Look for nop in this file :: ...\hardware\teensy\avr\cores\teensy\core_pins.h
    like >> asm volatile("nop\n");
    Hi defragster, I have no such file because I have no teensy board installed. But I will try to find the answer by iteration: I have a scope for doing the measurements.

    New question: How does the void loop() function work? By that I mean how do these commands digitalWriteFast(pinNum, LOW); and digitalWriteFast(pinNum, HIGH); actually work to get the different #define's of P1 through P4 to be shown on the output pin?

Posting Permissions

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