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

Thread: How can I do this ISR on the teensy 4.0??

  1. #1

    How can I do this ISR on the teensy 4.0??

    I have used this ISR trick to do multiple freq output for projects with arduino in the past, and now I want to do again for a teensy 4.0 project I am working on. I am having a hard time with understanding how to translate this over to the teensy 4.0 timers, can anyone help ? Thanks !



    Code:
    //** Arduino – Drive Multiple Speakers with Interrupts **//
    //** http://www.jeremyblum.com/2010/09/05...th-an-arduino/ **//
    
    /* Timer reload value, globally available */
    unsigned int tcnt2;
    
    /* Toggle HIGH or LOW digital write */
    int toggle1 = 0;
    int toggle2 = 0;
    int toggle3 = 0;
    int toggle4 = 0;
    int toggle5 = 0;
    
    /* Keep track of when each note needs to be switched */
    int count1 = 0;
    int count2 = 0;
    int count3 = 0;
    int count4 = 0;
    int count5 = 0;
    
    /* Frequency Output Pins */
    #define FREQ1 9
    #define FREQ2 10
    #define FREQ3 11
    #define FREQ4 12
    #define FREQ5 13
    
    //Setup Function will run once at initialization
    void setup()
    {
     /* First disable the timer overflow interrupt*/
     TIMSK2 &= ~(1<<TOIE2);
    
     /* Configure timer2 in normal mode (no PWM) */
     TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
     TCCR2B &= ~(1<<WGM22);
    
     /* Select clock source: internal I/O clock */
     ASSR &= ~(1<<AS2);
    
     /* Disable Compare Match A interrupt (only overflow) */
     TIMSK2 &= ~(1<<OCIE2A);
    
     /* Configure the prescaler to CPU clock divided by 128 */
     TCCR2B |= (1<<CS22) | (1<<CS20); // Set bits
     TCCR2B &= ~(1<<CS21); // Clear bit
    
     /* We need to calculate a proper value to load the counter.
     * The following loads the value 248 into the Timer 2 counter
     * The math behind this is:
     * (Desired period) = 64us.
     * (CPU frequency) / (prescaler value) = 125000 Hz -> 8us.
     * (desired period) / 8us = 8.
     * MAX(uint8) – 8 = 248;
     */
     /* Save value globally for later reload in ISR */
     tcnt2 = 248;
    
     /* Finally load end enable the timer */
     TCNT2 = tcnt2;
     TIMSK2 |= (1<<TOIE2);
    
     //Configure I/O Pin Directions
     pinMode(FREQ1, OUTPUT);
     pinMode(FREQ2, OUTPUT);
     pinMode(FREQ3, OUTPUT);
     pinMode(FREQ4, OUTPUT);
     pinMode(FREQ5, OUTPUT);
    
    }
    
    /* Install the Interrupt Service Routine (ISR) for Timer2. */
    ISR(TIMER2_OVF_vect)
    {
     /* Reload the timer */
     TCNT2 = tcnt2;
    
     count1++; count2++; count3++; count4++; count5++;
    
     if (count1 == 60)
     {
     digitalWrite(FREQ1, toggle1 == 0 ? HIGH : LOW);
     toggle1 = ~toggle1;
     count1 = 0;
     }
     if (count2 == 53)
     {
     digitalWrite(FREQ2, toggle2 == 0 ? HIGH : LOW);
     toggle2 = ~toggle2;
     count2 = 0;
     }
     if (count3 == 47)
     {
     digitalWrite(FREQ3, toggle3 == 0 ? HIGH : LOW);
     toggle3 = ~toggle3;
     count3 = 0;
     }
     if (count4 == 40)
     {
     digitalWrite(FREQ4, toggle4 == 0 ? HIGH : LOW);
     toggle4 = ~toggle4;
     count4 = 0;
     }
     if (count5 == 35)
     {
     digitalWrite(FREQ5, toggle5 == 0 ? HIGH : LOW);
     toggle5 = ~toggle5;
     count5 = 0;
     }
    }
    
    void loop()
    {
     //Do whatever else you want to do with your arduino!
    }



    code originally found here:
    https://www.jeremyblum.com/2010/09/0...th-an-arduino/
    Last edited by defragster; 02-19-2021 at 04:29 AM. Reason: used toolbar # to add [CODE] // code [/CODE]

  2. #2
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,753
    If read right - this handles starting the 8 us timer and shows pin toggle on expired count.


    Code:
    intervalTimer myTimer;
    
    * Keep track of when each note needs to be switched */
    int count1 = 0;
    int count2 = 0;
    int count3 = 0;
    int count4 = 0;
    int count5 = 0;
    
    /* Frequency Output Pins */
    #define FREQ1 9
    #define FREQ2 10
    #define FREQ3 11
    #define FREQ4 12
    #define FREQ5 13
    
    void setup() {
    
     //Configure I/O Pin Directions
     pinMode(FREQ1, OUTPUT);
     pinMode(FREQ2, OUTPUT);
     pinMode(FREQ3, OUTPUT);
     pinMode(FREQ4, OUTPUT);
     pinMode(FREQ5, OUTPUT);
      myTimer.begin(myISR, 8);  // myISR to run every 8 us
    
    // ...
    }
    
    
    /* the Interrupt Service Routine (ISR) for Timer2. */
    void myISR()
    {
     count1++; count2++; count3++; count4++; count5++;
    
     if (count1 == 60)
     {
     digitalToggleFast(FREQ1);
     count1 = 0;
     }
    
    // ... repeat for other FREQ#'s
    
    }
    
    void loop()
    {
     //Do whatever else you want to do with your arduino!
    }

  3. #3
    Thank you! I will give that a try.
    How can I do this with something with better resolution and will allow for much higher than audio frequencies? I would love to do this routine with 1/2 or 1/4 of the clock speed of the teensy 4.0

    Quote Originally Posted by defragster View Post
    If read right - this handles starting the 8 us timer and shows pin toggle on expired count.


    Code:
    intervalTimer myTimer;
    
    * Keep track of when each note needs to be switched */
    int count1 = 0;
    int count2 = 0;
    int count3 = 0;
    int count4 = 0;
    int count5 = 0;
    
    /* Frequency Output Pins */
    #define FREQ1 9
    #define FREQ2 10
    #define FREQ3 11
    #define FREQ4 12
    #define FREQ5 13
    
    void setup() {
    
     //Configure I/O Pin Directions
     pinMode(FREQ1, OUTPUT);
     pinMode(FREQ2, OUTPUT);
     pinMode(FREQ3, OUTPUT);
     pinMode(FREQ4, OUTPUT);
     pinMode(FREQ5, OUTPUT);
      myTimer.begin(myISR, 8);  // myISR to run every 8 us
    
    // ...
    }
    
    
    /* the Interrupt Service Routine (ISR) for Timer2. */
    void myISR()
    {
     count1++; count2++; count3++; count4++; count5++;
    
     if (count1 == 60)
     {
     digitalToggleFast(FREQ1);
     count1 = 0;
     }
    
    // ... repeat for other FREQ#'s
    
    }
    
    void loop()
    {
     //Do whatever else you want to do with your arduino!
    }

  4. #4
    Senior Member
    Join Date
    Aug 2013
    Location
    Gothenburg, Sweden
    Posts
    398
    You will not do any ISR based timing at more than a fraction of the processor clock divided by ( ISR setup cycles + ISR execute cycles + ISR return cycles). This might be fast compared to audio frequencies ( 600 MHz / 44 kHz = 13 kcycles approx) , your ISR will easily consume at least a couple of hundred clock cycles so the the timer update frequency most correspondingly lower, or the processor will be locked by timer interrupts.

  5. #5
    Isnt the F_BUS 150MHz in the Teensy 4.0 ? Id be happy with that.
    I got the code defragster posted running now (thanks again!). When I set to 1us and 2 counts I get 250khz for max.
    So it seems that 1mhz is the max for that interval timer library? What other options do I have?
    Last edited by Davy Oneness; 02-20-2021 at 02:26 AM.

  6. #6
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,753
    Is this the whole purpose or just a part of the project? Is any code needed to run in loop()? Do the frequencies ever change?

    A Float value can be passed in and it looks like a value down to 0.7291667 (?) will work with interval timer. If .begin() returns false the value was too small.
    Code:
    	bool begin(void (*funct)(), float microseconds) {
    		if (microseconds <= 0 || microseconds > MAX_PERIOD) return false;
    		uint32_t cycles = (float)(24000000 / 1000000) * microseconds - 0.5f;
    		if (cycles < 17) return false;
    		return beginCycles(funct, cycles);
    	}
    There is this library : github.com/luni64/TeensyTimerTool - not sure what it can arrange for fastest timer interrupts.
    > but the shorter the interrupt period - the more overhead from the interrupt processing - and the more time the calculation code in the _isr() will consume and the less time for loop() to do anything.

  7. #7
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    8,230
    I klicked on your link and just read the heading "Driving 5 speakers".

    I think you can do that by simply using the PWM outputs... ( analogWrite() )

    Or tone()
    Last edited by Frank B; 02-20-2021 at 07:26 AM.

  8. #8
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,753
    I was wondering the point of the code as well - indeed tone or PWM might give better results with less overhead.

Posting Permissions

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