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

Status
Not open for further replies.

Davy Oneness

New member
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 **//
//** [url]http://www.jeremyblum.com/2010/09/05/driving-5-speakers-simultaneously-with-an-arduino/[/url] **//

/* 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/05/driving-5-speakers-simultaneously-with-an-arduino/
 
Last edited by a moderator:
If read right - this handles starting the 8 us timer and shows pin toggle on expired count.


Code:
[URL="https://www.pjrc.com/teensy/td_timing_IntervalTimer.html"][B]intervalTimer[/B][/URL] 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!
}
 
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

If read right - this handles starting the 8 us timer and shows pin toggle on expired count.


Code:
[URL="https://www.pjrc.com/teensy/td_timing_IntervalTimer.html"][B]intervalTimer[/B][/URL] 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!
}
 
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.
 
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:
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.
 
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:
I was wondering the point of the code as well - indeed tone or PWM might give better results with less overhead.
 
Status
Not open for further replies.
Back
Top