Teensy3.1 and Flextimer(s?)

Status
Not open for further replies.

TelephoneBill

Well-known member
The Flextimer resource in Teensy3.1 is new to me. For newcomers, the Freescale K20P64M72SF1RM reference manual is not the easiest document to get to grips with :)

In chapter 36 of the reference manual, the FTM Memory map (page 775) suggests that there are actually three timers - FTM0, FTM1 and FTM2. The narrative doesn't state this, so I wondered if this was in fact the case? If so, can they be used independantly of each other?

I also notice that a Flextimer uses a 16 bit counter. If these are three independant Flextimers, can these be configured in series to form a 32 bit, or maybe a 48 bit counter?

Most examples I have seen wanting to count beyond 65,535 appear to use a small bit of code in an ISR to examine the overflow flag for one 16 bit counter, and then increment a variable as a more significant word. But I use a Teensyduino/Arduino environment, and this ISR method has a small amount of overhead which I may wish to avoid - mainly because it isn't always consistent.

Any help to get me started with Flextimer(s) would be appreciated.
 
In chapter 36 of the reference manual, the FTM Memory map (page 775) suggests that there are actually three timers - FTM0, FTM1 and FTM2. The narrative doesn't state this, so I wondered if this was in fact the case? If so, can they be used independantly of each other?

Yes, there are 3 of those timers, all independent.

Something you should understand about Freescale's manual is the later chapters are very generic. The FTM chapter is about that timer, which is identical info for chips that have only 2 of them and others that have 3 or 4 FTM timers. The idea is chapter 3 has the chip-specific config, about how many timers and things about the timers (like the number of actual channels) each has.

That is a pretty lazy approach to documentation on Freescale's part. They have hundreds of part numbers using pretty much the same peripherals, with only slightly different customization, so I'm sure it seemed like a good idea to them to document it this way. But it does make the manual a challenge to read. With their newest parts, it seems Freescale is starting to learn this approach sucks, so now they're putting the chip specific info into a section in the beginning of each chapter. Still not ideal, since the rest of the chapter is still the same generic stuff.

But for this chip, you have to read both the generic peripheral chapter and the section in chapter 3 which gives its specific config.


I also notice that a Flextimer uses a 16 bit counter. If these are three independant Flextimers, can these be configured in series to form a 32 bit, or maybe a 48 bit counter?

I've never tried to do this, so I really do not know for sure. There's a number of options in the SIM_SOPT4 register to reconfigure how each timer gets triggered, so maybe?

Most examples I have seen wanting to count beyond 65,535 appear to use a small bit of code in an ISR to examine the overflow flag for one 16 bit counter, and then increment a variable as a more significant word.

Certainly you can use the overflow interrupt to increment a variable.

But I use a Teensyduino/Arduino environment, and this ISR method has a small amount of overhead which I may wish to avoid - mainly because it isn't always consistent.

For the FTM timers, there's no extra overhead. Just use the interrupt function name and your interrupt gets called. The Teensyduino core library doesn't have any interrupt routine that adds any overhead. It does for the PIT timers and pin interrupts, but not for FTM.

Even when the core library (or another library) uses the interrupt, you can use attachInterruptVector() for forcibly get direct access to any interrupt. Of course, doing this will interfere with any other code needing that interrupt, and if other code calls attachInterruptVector() after yours, you lose control of that interrupt.

Still, if you want absolutely native access to an interrupt, you can always use attachInterruptVector().

Any help to get me started with Flextimer(s) would be appreciated.

Maybe look at some of the libraries that use the FTMs? FreqMeasure, PulsePosition and FreqCount might be useful. FreqMeasure uses the overflow to extend the 16 bit count to 32 bits, so maybe look at that one first?
 
Considered a number of examples of using Flex Timers from others. Managed to get code working well. To help anyone wishing to start, I have attached the following simple example of a basic roll-over Flex Timer using the ISR and a 32 bit variable increment when FTM0 rolls past 0xFFFF. This will count up to 5,864,062 secs.

I had expected the clock to be 96 MHz (what I thought was the 'system clock'). But it turned out to be 48 MHz, which I think is known as the Peripheral System Clock. Is this the fastest clock available? Or is there a way to up this to 96 MHz?

//FLEX TIMER Example (Teensy 3.1)
//===============================
//Author: TelephoneBill
//Date: 03 SEP 2015
//Version: 150903/1
//Comments: A simple test routine to demonstrate the operation of Flex-Timer FTM0.
//Using SERIAL MONITOR, type 'q' to start FTM0 and 'a' to stop it. Type 'r' to read
//the number of times that the counter overflows (timer FTM0_MOD set to max count 0xFFFF).
//TimerOverflowCount can be read "on-the-fly" - no need to stop it first.
//The clock source is the "Peripheral System Clock" which for Teensy 3.1 is 48 MHz.
//The interrupt is generated on timeout passing the FTM0_MOD value (0xFFFF).
//No need to reset FMT0_CNT to zero in ISR because this happens on roll-over from FFFF to 0000.
//Max value of TimerOverflowCount = 4294967296 (32 bits) = 5,864,062 secs.

//Declare variables
const int LedPin = 13;
volatile unsigned int TimerOverflowCount = 0;
int Byte1;

//Config function for FTM0 (Flex Timer 0)
void configFTM0() {
//set write-protect disable (WPDIS) bit to modify other registers
FTM0_MODE = 0x05; //FAULTIE=0 FAULTM=00 CAPTEST=0 PWMSYNC=0 WPDIS=1 INIT=0 FTMEN=1(no restriction FTM)

//FTM0 configuration values
FTM0_SC = 0x00; //set status/control to zero = disabled (enabled in main loop)
FTM0_CNT = 0x0000; //reset count to zero
FTM0_MOD = 0xFFFF; //max modulus = 65535 (gives count = 65,536 on roll-over)
//Note - not using any channel interrupts - interrupt is from TOF

//enable FTM0 interrupt within NVIC table
NVIC_ENABLE_IRQ(IRQ_FTM0);
}

//Interrupt Service Routine for FlexTimer 0 Module
extern "C" void ftm0_isr(void) {
//FTM0_CNT = 0x0000; //no need for count reset - happens on roll-over
if ((FTM0_SC & FTM_SC_TOF) != 0) { //test if timer overflow flag set
FTM0_SC &= ~FTM_SC_TOF; //clear timer overflow flag (~ = bitwise NOT)
}
TimerOverflowCount++; //increment overflow counter
}

//LED flash once routine (used to indicate keyboard input received OK)
void FlashLed(){
digitalWrite(LedPin, HIGH);
delay(100);
digitalWrite(LedPin, LOW);
}

//Program setup
void setup() {
pinMode(LedPin, OUTPUT); //LED will be used to indicate keyboard input
Serial.begin(115200); //use fastest baud rate for SERIAL MONITOR
configFTM0(); //prepare to use Flex-Timer 0
delay(1000); //wait 1 sec to allow SERIAL MONITOR to initialise
Serial.println("Press 'q' to enable timer, 'a' to disable");
Serial.println("Press 'r' to read Counter");
}

//Program loop
void loop() {
//test for keyboard input
// (Note - FTM0_SC [TOF=0 TOIE=1 CPWMS=0 CLKS=01 (Periph Sys Clock 48 MHz) PS=000 [prescale divide by 1])
if (Serial.available() > 0) {
Byte1 = Serial.read(); //read incoming byte
if (Byte1>0x60) {
switch (Byte1) {
case 0x71: //q (start timer)
FTM0_SC = 0x48; //enable Peripheral System clock (48 MHz), no prescale
FlashLed();
Serial.println("Timer enabled");
break; //end of q
case 0x61: //a (stop timer)
FTM0_SC = 0x00; //disable clock
FlashLed();
Serial.println("Timer disabled");
break; //end of a
case 0x72: //r (read counter)
FlashLed();
Serial.print("Overflow Count = ");
Serial.println(TimerOverflowCount);
break; //end of r
}
}
}
}
 
Last edited:
You could feed the output of one timer to an external pin and then use this pin as an external clock input for a second timer. Then they are cascaded without the variability of an interrupt routine.
 
Thanks Jonr - that's a good and interesting idea. My experiment is trying to very accurately count/time the frequency drift of a 10 MHz oven controlled xtal oscillator (OCXO). This is the reason for avoiding ISR variability. Ideally I will phase lock the OCXO to a 1PPS signal using the Teensy 3.1 DAC to control the OCXO.

So the challenge now is to understand how "Channels" work with FTM (to get an output from one FTM and an input to the next FTM). The Freescale manual makes this hard work.
 
You could send the 10 mhz signal into the teensy as a FTM external clock source. Then have the 1 PPS signal cause the FTM to capture (see "input capture mode") the clock value. Because it won't be far off, you could infer the number of rollovers.
 
If the timer modulus value is set to 9999 (10000-1) then the number of rollovers will be 1000 plus/minus 1 and that will be seen as rollover/rollunder in the capture value. The slow change of the capture value will be the drift of the OCXO and/or the GPS jitter.
 
Hi All,

I'm trying to migrate to Teensy31 a code I wrote to run on Arduino Mega (ATmega2560 chip)

The code is a pulse train generator to control stepper motor drives, dir/step type drivers.

In Atmega2560 I used a timer triggered interrupt for generating each pulse. The timer worked in “free running mode” and fired an interrupt every time the timer count reached the value of a “comparator register”

Let's say the comparator register value is set to 6300. When the timer count reaches 6300 the ISR is fired. In that moment, the ISR generates a drive pulse and sets next firing time changing the value of the “comparator register” to, say, 13400. Now, when the timer count reaches 13400 a new interrupt, pulse and comparator setting are fired. And so on

The timer is running all the time and when the timer reaches the max count, it overflows and continues counting from zero.

I'm looking for what could be the most suitable timer in teesny31 (MK20DX256 chip) to run this code. I suspect the PIT timers or the TimerInterval library are no well suited for this purpose.

Can one of the FlexTimers (FTM) be configured to work this way?

(sorry for my horrible English)
 
@FAlameda - I think both FTM (Flextimer) and PIT (Programmable Interval Timer) can fire an interrupt. Probably the simplest would be PIT because it does exactly as you describe. FTM uses "channels" to engineer activity with its timer function. Its the understanding of how to use these channels that is my current problem/study task. They are very flexible (and can be used as either input or output activity) which makes the understanding a bit more tricky. The manual only gives spec data, and the few app notes issued by Freescale are very specific functions. These app notes may be useful for your stepper motor project.
 
@mlu - I like your timer modulus thinking, but the precision I am looking for exceeds that which the onboard Teensy 3.1 crystal can deliver. So the jitter in the roll-over could be (and probably will be) more down to temp variations in the Teensy crystal than in the OCXO. My OCXO is actually a double oven (cheap on ebay) so its stability is in region of e-11 or e-12. Surprisingly, GPS 1 PPS (from cheap UBlox module) has quite a large amount of jitter itself caused by acquiring or losing a satellite. The average long term is very accurate (e-13), but the short-term is (relatively) appalling (can suddenly jump 100 nanoSecs). So to get around this GPS jitter, I am using a 1PPS signal from an RFS (Rubidium Freq Standard - can buy ebay RFS 1PPS very cheap $50 even today). This is very stable - circa e-11. If you compare (on a scope) GPS, RFS and OCXO you clearly see GPS is the bad guy short term. So I calibrate RFS (using digital RS232 interface) against GPS over hours, then use RFS as gold standard timing.

But developing your roll-over principle further, if I input both RFS 1PPS and OCXO signals into Flextimer (FTM), then the Teensy crystal is common to both measurements, so should be able to cancel. I'm thinking now to have two "input capture channels" (1=reading FTM with RFS, 2 = reading FTM with OCXO derivative). Then some maths. Can even use full precision of FTM count (65536) to make the two readings, and any drift of OCXO against RFS, then Teensy can make the adjustment in OCXO control voltage to compensate drift.

As long as there is no jitter in the "capture channels", then the readings should be good. Even if there was, this might average out if symmetrical distribution about a mean.

So the problem to solve now is "Can I use two channels simultaneously to capture FTM count? And if so, how do I code this practically?". Any code snippets to illustrate would be gratefully received. Then I can add "understanding" of this - to this post - and will be good for other Teensy FTM users.
 
@mlu - On re-reading my post, this sounds a bit garbled. Yes, you can use 10 MHz as external clock, and use one capture channel for RFS. The values then computed will be from a 10 MHz source.

However, the Teensy FTM clock runs at 48 MHz, which is five times faster and the maths then becomes five times "greater precision" in a given time period. That was the motivation for using the Teensy internal clock as the FTM counter drive source, rather than using the external 10 MHz as the drive source. But the penalty is using two capture channels rather than one. Hope this explains my own thoughts :)
 
Knowing if the Teensy crystal oscillator, without any frequency control, or the OCXO has the smallest jitter, on different timescales, is hard.

The oven control for an OCXO introduces jitter from the control algorithm, but it removes variations due to temperature variations. Adding a voltage control loop will increase the jitter. Conditioning with GPS will also add a control loop that tends to increase short term jitter but improve long term stability.

The non controlled crystal oscillator has very good short term stability, IF temperature and supply voltage are stable.

Now the 48 MHz doesnt give better precision than 10MHz, but it does give better resolution, remember that it is run from a 16MHz crystal, so the 48MHz clock cannot be more precise than the 16MHz crystal, and the PLL will introduce some added phase jitter.

I cannot give more precise advice on the exact implementation without checking a bit deeper into the RM for the teensy, but I would do something like this:
Setup a flextimer clock to count 10000 clocks (1KHz with 10MHz clock), then connect the 10MHz as a clock source for that timer as jonr suggests, and the 1PPS as a capture trigger.

The number of rollovers will be 1000 unless the capture value is very close to 0 or 9999.
 
Trying to test out the use of 10 MHz OCXO as external clock to Flextimer 0, but have hit a problem...

It appears that to use an external clock for FTM0 there needs to be three configs actioned:-
(1) Set FTM0_SC = 0x58 (TOIE = 1, CPWMS = 0, CLKS[1:0] = 11 in SC register, PS[2:0] = 0).
(2) Set FTM0CLKSEL = 0 (bit 24) in SIM_SOPT4. This chooses FTM_CLK0 pin as the external clock source.
(3) Choose an external Teensy pin to multiplex on to FTM_CLK0 pin using the appropriate PORT CONTROL register.

This last action (3) is my problem. I cannot see how to select an external Teensy pin using any PORT CONTROL register. I expected this to be an ALT function, but in looking through the ALT table in section 10.3.1 of the RefManual, there is no mention of FTM_CLK0. There is a mention of "FTM_CLKIN0", but I'm guessing this is not the same thing.

I am assuming that you can select a PORT pin (e.g. such as PORTC Pin 23) as the multiplex pin to connect the 10 MHz OCXO into. The cautionary note in SIM_SOPT4 discussion suggest this to be the case. If this is wrong and you need to use the actual chip pin 32 (EXTAL0) as ALT4 on PORTA18, then thats a soldering job (not nice).

The good news is that I did manage to capture flextimer values using PORTC1 (Teensy pin 22) as the 1 PPS signal input (using statement "PORTC_PCR1 |= 0x400;" - ALT function 4 on Chip Pin 44), and I also remembered to reset the event flag (FTM0_C0SC) each time after reading the flextimer value FTM0_C0V. If I run this test using the SYSTEM CLOCK rather than an EXT CLOCK, then I get sensible values being output on screen. And they stop if I disconnect the 1 PPS signal.

Hoping someone can advise. Desoldering just to use an external clock for Flextimer would be a step too far.
 
I guess FTM_CLKIN0 and FTM_CLK0 is the same thing, and yes it sure seems to be sharing pins with the external 16 MHz crystal. So using it will mean that you can run the Teensy from to OCXO, might be what you want and it might be a can of worms.
 
I am glad you were able to figure out the RFS and so on. The units I see on eBay right now are downright intimidating. But perhaps they're easier to use than they seem.

Based on your comments, I'm considering buying a vanguard 0.1PPM Tcxo module to use as a reference so I won't need a GPS signal to do my temperature trimming of the RTC crystal. That cost looks much more reasonable.

See http://www.ebay.com/ulk/itm/141259820137 for example. That could be easily integrated with a dedicated power supply on a backpack to a teensy LC. 6.144 MHz TTL signal should be low enough in speed to capture reliably with an ISR. Then generate a 1pps TTL signal from there.
 
Last edited:
I think that external clock feeding of FTMs is not allowed in Teensy. Any of the 3 FTM can be configured to use the “physical” pins FTM_CLKIN0 or FTM_CLKIN1 as external clock source but this pins, K20 pins 32 and 33, are used by the Teensy crystal.

A possibility is to use the 48 MHz clock of Teensy and capture the 1PPS 1Hz signal in a channel and capture the OCXO signal in other channel. Each capture fires an interrupt so that the OCXO signal can’t have a frequency as high as 10 MHz.

The frequency of the OCXO signal would have to be divided to 0.5 – 1 Mhz or so prior to use it to fire the channel capture. I think that this division would not necessarily produce loss of resolution or accuracy.

Perhaps the FTM1 timer, whose “physical” pins are accessible in Teensy, could be used as a frequency divider but this would involve the use of an interrupt. If the frequency is not high, FTM1 or FTM2 can count edges of a signal if configured as “quadrature decoders” (the signal is injected in the phaseA pin and the phaseB pin is maintained at logic 1)

The problem is that, when they are configured as “quadrature decoders”, the “output compare” does not work (I believe), so an overflow fired interruption should be used to divide the frequency. I'm not sure if this would create problems of accuracy.
 
The 6.1MHz TTL signal may be capture-able... There is also a 3MHz model, which would allow the CPU to run about 30x faster than the ISR has to go.

Alternatively, could you use a counter or divider chip that works as a divider to slow the signal down?

I just looked some up on digikey - not cheap but not that expensive either. The divider could easily be configured to allow significant reductions in clock speed, which in turn should make the Teensy happier re: capturing the TTL signals. However, I'd imagine you quickly run into issues where on the one hand you can trim the TCXO to perfection using a GPS for several hours as a reference if you allow a relatively high input frequency vs. the problem of accurately registering every TTL pulse.

That said, the board required would be pretty small. I'd add a dedicated power supply with a high PSSR like the ADP150 series to power the clock, divider, while the reference GPS would run off the Teensy VUSB. But setting this up could be an interesting challenge, i.e. how to debug the output without influencing the results. For example, it might make sense to store 60 seconds of data in a buffer and then disable the DAQ for a second while the Teensy squirts the whole load to the CPU.

I also wonder if setting up such a system without interrupts wouldn't potentially work better. That is, avoid the additional clock cycles associated with dropping into an interrupt loop and instead manually monitor a digital read pin continuously. Could be an interesting one to do a comparison with.
 
Last edited:
@mlu - I was afraid they might be the same (but hoping not, and someone would show me another way).
@FAlameda - Your comment that "FTM1 and FTM2 can count edges" is intriguing and worth exploring further. I confess to raising an eyebrow (if true) that this Freescale chip could not use any of its timers as a general (free-running) counter (without interferring with the cpu crystal). But your suggestion may be the solution. I will examine this when time allows.
@Constantin - The RFS module I'm using is an FE5680B. Much cheaper than the FE5680A but only has 1PPS via a DB15 output. There are several "A" versions (all slightly different) but some have 10 MHz outputs (though these are expensive second hand). There are two internal signals (20 MHz and 30 MHz) on the "B", but you would have to micro-solder wires (tricky) to get either of them out. I did not want to "disturb" the internals in case I upset the Ruby mechanism, so my idea was to use the 1PPS as a reference in phase to lock the OCXO to, and get a nice very accurate 10 MHz that way. The Teensy DAC, by the way, is brilliant at controlling the OCXO and a simple maths "dither" mechanism can even get better than 12 bits. I have a simple resistor chain to the OCXO stabilised +7 volts (DAC connected at bottom of resistor chain) and tapped at a fraction to feed the OCXO control pin (around +4 V) - so no op amp needed :) - works fantastic, and gives exceptionally stable control of the OCXO (as good as 1 nanoSec phase adjustment). Thanks for info on the TCXO - might try one.

The idea of feeding the OCXO into a Flextimer (as suggested) is basically a FREQ Lock Looped (FLL). This has advantages of simplicity, if I could have used any other PORT pin. But that idea looks dead now on FTM0 (upsetting the 16 MHz crystal might upset the USB timing as well). If FTM1 or FTM2 can be used, then that might change things (work in progress on this).

But my current thoughts are that a true PHASE Locked Loop might be simpler. The RFS 1PPS is amazing in its stability (jitter only two nanoSecs at most every second). I have already tested a PLL with the OCXO, using (as suggested) a 74HC390 dual decade divider (one transistor interface needed to level change) so can have 5 MHz, 2 MHz, 1 MHz, 500 KHz, 200 KHz or 100 KHz sq waves available. Any of these gives a decent TTL "edge reference" for phase determination. Using 1 MHz, I read both this signal, and the 1PPS, into PORT D5 and D6 pins, and used a polling loop (interrupts disabled), just to catch the "instants" of both edges, and drive them together by up/down increments of the DAC. The performance of this is +/- 20 nanoSecs stability of the OCXO phase with respect to the 1 PPS. Good, but I'd like better... the cause of the 20 nS is probably the asynch nature of the Teensy crystal.

What might be worth a try is to use two channels of a Flextimer. One each to read the FTM0 using its System Clock. Then compare the 1 MHz (OCXO) edge "FTM reading" (e.g. FTM0_C0V) with that from the 1PPS edge (e.g. FTM0_C1V) and use some "filtering" maths prior to setting the DAC control. I'm hoping here to reduce the phase difference "wandering" down to minimal (the actual phase not important as long as its constant). The RFS and OCXO can give accuracy in region e-10 or e-11. For 10 MHz, e-10 is within one milliHertz - 10,000,000.000 Hz :) !! That's a tempting prize if Teensy can do it for me.
 
You could perhaps use FTM1 in quadrature mode, count direction encoding.
OCXO connected to phase A, FTM1_QD_PHA, and phase B set constant then the 1PPS to the capture input
 
It sounds a good idea - will investigate later when time allows. In the meantime, I have some very good news to report. I managed to get CH1 working (very simple) as well as CH0 on FTM0 using the system clock. These use Teensy 3.1 pin 23 for CH1 and pin 22 for CH0. I set the modulus for FTM0 at 47999 (appropriate for 48 MHz system clock). I wrote an ISR for rollover, and reset FTM0 COUNT to zero in the ISR as well as resetting the TOF overflow flag. I also incremented a rollover integer variable just to keep check on the number of rollovers (rate should be 1 KHz, like your original idea).

Here is a scope picture to show events... Trace 1 (Yellow) is the edge of a 100 KHz sq wave derived from the 10 MHz OCXO via the 74HC390 dual decade divider (Pin 23 CH1 positive going edge). Trace 2 (Light Blue) is the edge of the RFS 1PPS and also the synch trace (Pin 22 CH0 positive going edge). Trace 3 (Purple) is the 10 MHz OCXO sine wave = locked to Trace 1 sq wave.

Ch0Ch1Coincidence.jpg

I could adjust Trace 1 to lead or lag Trace 2 (very slow, sliding left or right using a manual control of the DAC value). As I did so, the count values for CH0 and CH1 came into close agreement until eventually they were co-incident. The shrinking count difference also agreed precisely with scope display, being one count value difference for every 20 nanoSecs (roughly) of scope Trace 1 versus Trace 2 separation (which agrees with the 48 MHz clock rate).

Typical values (every second) were:
Secs = 1200, CH0 Count = 19714, CH1 Count = 19714
Secs = 1201, CH0 Count = 5771, CH1 Count = 5771
Secs = 1202, CH0 Count = 39998, CH1 Count = 39998

The system clock is not precisely 48 MHz, so I think this is the reason why the readings are drifting in (absolute) value, but the co-incidence was a great pleasure to observe. And as the two traces drifted 20 nanoSecs apart again (Trace 1 moving to the right of Trace 2) then the values again differed by one count.

So I now have a very accurate method of reading the relative phases (difference) of the OCXO sq wave relative to the 1 PPS. Possibly by using some "maths" filtering on the numbers over periods of minutes, then I should be able to get a good control signal to automatically adjust the DAC. We shall see exactly how good. That's the next phase of work.

For anyone reading who is a newbie to "channels", here is my code snippets to enable them (do NOT use "pinMode" to set as inputs):

//initialise Flextimer
FTM0HiCount = 47999;
FTM0_MODE = 0x05; //set write-protect disable (WPDIS) bit to modify other registers
//FAULTIE=0, FAULTM=00, CAPTEST=0, PWMSYNC=0, WPDIS=1, INIT=0, FTMEN=1(no restriction FTM)
FTM0_SC = 0x00; //set status/control to zero = disabled (enabled in main loop)
FTM0_CNT = 0x0000; //reset count to zero
FTM0_MOD = FTM0HiCount; //max modulus = 47999 (gives count = 48,000 on roll-over - 1 KHz)
FTM0_C0SC = 0x04; // CHF=0, CHIE=0 (disable interrupt, use software polling), MSB=0 MSA=0, ELSB=0 ELSA=1 (input capture - rising edge), 0, DMA=0
FTM0_C1SC = 0x04; // CHF=0, CHIE=0 (disable interrupt, use software polling), MSB=0 MSA=0, ELSB=0 ELSA=1 (input capture - rising edge), 0, DMA=0

//Note - not using any channel interrupts - interrupt is from TOF
NVIC_ENABLE_IRQ(IRQ_FTM0); //enable FTM0 interrupt within NVIC table

//configure Teensy input capture channels
PORTC_PCR1 |= 0x400; //MUX = alternative function 4 on Chip Pin 44 (FTM0_CH0) = Teensy Pin 22
PORTC_PCR2 |= 0x400; //MUX = alternative function 4 on Chip Pin 45 (FTM0_CH1) = Teensy Pin 23

//enable system clock (48 MHz), no prescale
FTM0_SC = 0x48; // (Note - FTM0_SC [TOF=0 TOIE=1 CPWMS=0 CLKS=01 (System Clock 48 MHz) PS=000 [no prescale divide])

And the ISR routine:

// ISR routine for FlexTimer0 Module
extern "C" void ftm0_isr(void) {
FTM0_CNT = 0x0000; // reset count value
if ((FTM0_SC & FTM_SC_TOF) != 0) { //read the timer overflow flag (TOF in FTM0_SC)
FTM0_SC &= ~FTM_SC_TOF; //if set, clear overflow flag
}
FTM0CountOVFlow++; //increment overflow counter
}

And to read the channels:

FTM0Ch0CountValue = FTM0_C0V; //current captured count value
if ((FTM0_C0SC&0x80) != 0) { //look for channel event flag
FTM0_C0SC &= ~0x80; //clear channel event flag
FTM0Ch0Flag++;
}
FTM0Ch1CountValue = FTM0_C1V; //current captured count value
if ((FTM0_C1SC&0x80) != 0) { //look for channel event flag
FTM0_C1SC &= ~0x80; //clear channel event flag
FTM0Ch1Flag++;
}

The channel flags were supervisory signals just to show that something was actually happening on each channel (can be removed).
 
Hey Telephonebill, all that is very inspiring. A few moons ago I did some some work trying to create a TCXO using the standard CFS-206 RTC crystal and a DS18B20 temperature probe. The research suggested that as long as the power was left on (i.e. no operation solely on VBAT) that the CFS206 could perform at better than +/- 1PPM, especially if left around room temperature. Back then, I was using a GPS receiver from Adafruit and the Teensy to clock the difference between the various time pieces. I got it down to microseconds in terms of resolution, with a planned upgrade in the distant future to use CPU clock cycles instead.

Your post inspired me to sniff around the net and look at various time pieces, clocks, and so on.You may be interested to hear that the standard 5x3.2mm crystal used on the Teensy 3.x is also available as a VCTCXO - though it requires some additional circuitry, such as a 3V, 1.5V external power supply, some caps, etc. Nothing earth-shattering but basically requiring a DIY Teensy board to hold it all unless you are very good at de-soldering and resoldering pads, eliminating the right connection to the Teensy, and so on.

However, this chip gave me the thought that combined with a PLL chip and the right clock divisor chips one could come up with something phase locked at a fairly low cost which then would allow a very accurate investigation of various CFS206 crystals. The main issue here, however, would be how to determine CFS-206 behavior as a function of changing the ambient temperature. Plus, I imagine that an un-modified CFS-206 in a socket would behave differently than one with soldered pins that have been clipped (with all the heat sinking effects that entails, and so on).

So, instead, I would consider building a disciplined VCTCXO which uses a GPS PPS feedback to produce a very stable 1PPS clock source. Then, ditch the CFS206 and instead consider something like the SITIME 1552 whose marginal cost over the CFS206 is marginal (about $1) but which offers TCXO operation. The thing doesn't even need a bypass capacitor and runs right off 3.3V! Use the PPS signal to figure out any offsets / adjustments needed and then you have a very good RTC.

Some of the better TCXO's are likely to be found on Digikey vs. using a source on eBay that may or may not be selling relabeled rejects. I found the prices to be somewhat comparable, so I'd consider digikey over eBay in this case. For example, a 10MHz 0.1PPM TXCO can be as little as $23, and a 2x better 50ppb TCXO can be as low as $40. Mind you, the references there go down to +/-0.1PPB... and through-hole components tend to be more expensive.
 
... as interesting as the MEMS based TCXO is, however. I wonder if the RTC circuit inside the Teensy would play nice with it? I presume one would connect the TCXO oscillator output to EXTAL while leaving the XTAL pin floating?

Just occurred to me that the marginal cost over the solution that uses a DS18B20 solution is actually zero, as the DS18b20 can be eliminated. So other than the insane size of the solderballs underneath the CSP package, the SIT1552 seems like a pretty good upgrade option for the Teensy. Maybe onehorse can make an appallingly small TCXO upgrade board with a small lead to the RTC EXTAL hole? :p
 
I think the ISR does not need to clear the timer counter (FTM0_CNT = 0x0000; // reset count value). If modulus is 47999, when the counter reaches 47999 the timer will fire an overflow interrupt and continue counting from zero.

If you need to generate an interrupt when the counter goes through a value and continue counting up, that is not the case, you will use an "output compare" channel interrupt. The modulus interrupt generates an overflow interrupt and rollovers the counter.

If the ISR firing lag is not constant, the line FTM0_CNT = 0x0000; which clears a second time the counter, could introduce a disturbance in the timing.
 
@Constantin - There is a lot of fun to be had playing with oscillators, crystals and PLL chips like a 4046. In the UK, I have two additional sources of 1 PPS: (i) MSF60 (our equivalent of WWVB) and (ii) BBC Radio 4 Long Wave on 198 KHz (ferrite rod receiver and divide the received carrier freq by 198,000). I'm still making comparisons between them all. The UBlox NEO-7 is a nice cheap GPS device too. But you cannot beat a Ruby Freq Standard for stability (other than a Caesium, of course). If you are "into" atomic clocks, there is a new generation of "Coherent Population Trapping (CPT)" modules, which are now creating atomic standard modules size of 2 inch square by 0.7 inch thick. I look forward to these on eBay in years to come :) !! Have a read of CPT because it is very interesting and behaves like an LC circuit inside an atom, but without the need for a microwave cavity.

@FAlameda - Thanks for correcting my error - the statement "FTM0_CNT = 0x0000;" is NOT needed (and will indeed upset the 1 KHz timing if included). The explanation is given in RM section 36.4.3.1 and states that the value of FMT0_CNTIN will be loaded immediately after the MOD value has been reached (presume that CNTIN = 0x0000 by default on reset). It also states that the TOF interrupt flag will be set on the transition between MOD and CNTIN (useful to know).

More experimental research to report... I have been playing with manual control of the DAC today and observing the count difference between CH1 and CH0. It looks to be very, very good. Could give me a "software phase detector" that is reliably accurate to a few nanoSecs. There is a degree of probability intoduced when you get down to a phase difference of one or two - or even zero - counts. This "flickers" say on "0" to "-1" and will depend on the probability of a system clock edge falling in the gap time between the channel readings. This seems also to be true of other values (e.g. difference = "2" etc). I therefore presume (and will verify experimentally) that this probability can give me "sub-integer" control of the phase comparison. If proved true, then by using some maths on the channel difference count values (percent time at "-1" and percent at "0") then it should prove a much superior method of "software phase control" in my PLL (of the RFS 1PPS and the 10 MHz OCXO) to that previously looking at D6/D5 pin values.

Another major advantage of this "software phase detector" is that it gives proportional values, not just "bang/bang" like the D6/D5 method. This means that professional PID (Proportional/Integral/Differential) control loop technology may be employed to rapidly get to the required phase lock in the minimum time. Is this a first? Have we just invented a new software phase control method :) !! Its cetainly independant of temp and the system clock crystal frequency.
 
Status
Not open for further replies.
Back
Top