Modifying my source code for Teensy

Status
Not open for further replies.

eduk

Member
I've just got lost in the manuals for the MKL26Z64VFT4 and wondered if anyone her could help?

The code here is for the Arduino nano. It needs to work in a microsecond or so and so I've bypassed the normal Digitalread and digital write commands and addressed the digitalread port DDRD and then written to Port D with a binary command.

The teensy is much faster but doesn't like DDRD, etc, because it's specific to the arduino's chip.

So I need to do a similar thing on the teensy, but how do I set up an interrupt and find the commands for addressing the ports without reading the 600 page manual?

Ed


/*

*/

// This code is to take an input from pin D2 and output Rx blank on D3 which has a 2us delay on the falling edge and output Tx blank on D4 which has a 2us delay on the rising edge.


const byte interruptPin = 2;
volatile byte state = 0b00000000;
const byte rise_delay =6;
const byte fall_delay = 5;

void setup() {
//setup port D pins 3 and 4 as outputs. Pin 3 = RX_blank; Pin 4 = TX_blank//
DDRD = DDRD|B00011000;
//start with interrupt on rising edge//
attachInterrupt(digitalPinToInterrupt(interruptPin), rise, RISING);
}

void loop() {
// loop goes on forever with no actions so interrupts are serviced on rising and falling edges//


}

void rise() {
//Delay TX blank after rising edge//
//turn on Rx_blank//
PORTD=0b00001000;
//turn on Tx_blank as well//
delayMicroseconds(rise_delay);
PORTD=0b00011000;
detachInterrupt(digitalPinToInterrupt(interruptPin));
attachInterrupt(digitalPinToInterrupt(interruptPin), fall, FALLING);
}

void fall() {
//delay Rx_blank after falling edge//
PORTD=0b00001000;
delayMicroseconds(fall_delay);
PORTD=0b00000000;
detachInterrupt(digitalPinToInterrupt(interruptPin));
attachInterrupt(digitalPinToInterrupt(interruptPin), rise, RISING);
}
 
just try digitalReadFast/digitalWriteFast - you will be surprised how fast it is - esp. if you're using it with a const pin number.

edit; I see you're using delays anyway - so what's the point to use direct port access?
 
Last edited:
just try digitalReadFast/digitalWriteFast - you will be surprised how fast it is - esp. if you're using it with a const pin number.

edit; I see you're using delays anyway - so what's the point to use direct port access?

I have a read input on port 2 and I want a 2us delayed output on port 3. On the Arduino I get the 2us delay but an additional 3us delay from the micro.

I got my code converted for the Teensy but it looks like the problem is I have is that I am using the Teensy LC which has a 16MHz clock (according to a schematic I found on the internet). I thought I was running at 48MHz and so would be 3 times as fast.

What I am trying to do is to delay my rising edge by a delay.
 
This might be a case where something simple & easy becomes quite a challenge by "overthinking".

I ran copy of your code here, with the AVR port stuff replaced by digitalWriteFast, and a PWM signal to generate the interrupt pulse for testing.

Code:
const byte interruptPin = 2;
volatile byte state = 0b00000000;
const byte rise_delay = 6;
const byte fall_delay = 5;

void setup() {
  // PWM waveform - connect to pin 2 for testing
  analogWriteFrequency(23, 1000);
  analogWrite(23, 4);
  //setup port D pins 3 and 4 as outputs. Pin 3 = RX_blank; Pin 4 = TX_blank//
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  digitalWriteFast(3, LOW);
  digitalWriteFast(4, LOW);
  //start with interrupt on rising edge//
  attachInterrupt(digitalPinToInterrupt(interruptPin ), rise, RISING);
}

void loop() {
  // loop goes on forever with no actions so interrupts are serviced on rising and falling edges//
}

void rise() {
  //Delay TX blank after rising edge//
  //turn on Rx_blank//
  digitalWriteFast(3, HIGH);
  //turn on Tx_blank as well//
  delayMicroseconds(rise_delay);
  digitalWriteFast(3, LOW);
  detachInterrupt(digitalPinToInterrupt(interruptPin ));
  attachInterrupt(digitalPinToInterrupt(interruptPin ), fall, FALLING);
}

void fall() {
  //delay Rx_blank after falling edge//
  digitalWriteFast(4, HIGH);
  delayMicroseconds(fall_delay);
  digitalWriteFast(4, LOW);
  detachInterrupt(digitalPinToInterrupt(interruptPin ));
  attachInterrupt(digitalPinToInterrupt(interruptPin ), rise, RISING);
}

Here are the waveforms my oscilloscope sees.

file.png

Notice on the right hand side the scope is showing the pulse width measurements.

Here's how I tested the hardware.

DSC_0358_web.jpg
 
What I am having trouble with is that I start the interrupt on the rising edge of your top trace (read on pin2) and I want zero delay to the rising edge of your middle trace (write on pin 3). On both the Arduino nano and teensy LC this seems to be variable at about 3us. I'm hoping to get this delay to below 1us.
 
I'd look into using one of the LC's TPMs. You'd need to use a combination of input capture and output match modes, switching between them at every interrupt as necessary.

Use an output match channel as your delayed output (Tx_blank). Set it to fire a fixed delay past the captured timer value.

Use direct write to the PORTSET and PORTCLEAR registers at the capture interrupt for the output that needs to change immediately with your trigger signal (Rx_blank).
 
Agreed, user 1 us latency is easy on the much faster boards. ;)

You might be able to do better if you use attachInterruptVector() to have your function called directly, so you can avoid the overhead of attaxhInterrupt’s handler. But you’ll want to carefully choose 2 pins on different native port, so you can skip the work of checking which pin. You’ll also need to clear the port interrupt flag, but easy to just copy that from the attachInterrupt handler.

Also use FASTRUN on your handler function, so it’s in single cycle RAM. Again, this helps most on the faster 3.X hardware which had dual 32 bit buses to memory, but may also help a bit on Teensy LC.
 
Thanks guys, I'll get a teensy 3.2 and get this working and then try out the other solutions later!
 
my teensy 3.2 arrived today and works beautifully. Thanks to all who helped me with this!
Where do I find the document on all the teensy Arduino - style commands?
 
I've now been asked to add a new feature to this delay circuit. We would like to shape the output rise and falltimes to decrease the high frequency content of the waveform; it's possible we may be able to manage with one output. I could feed one of the digital outputs into a D to A and have a few rise points, but before I start on this I wanted to find out what problems I may run into; do you think this is possible on the Teensy 3.2 or would I need a faster Teensy? It's probably going to be something like maintaining the timing above and having a 1us rise and fall time.
 
Status
Not open for further replies.
Back
Top