What's the relation between Teensy 3.6 pins and the PWM MUX value?

Status
Not open for further replies.
I'm learning how to use PWM on Teensy 3.6, and I stumbled upon an issue determining what pins to use on Teensy to get the FTM channels to pins.

So starting from this thread: https://forum.pjrc.com/threads/4082...-clock-for-FTM-timers?highlight=telephoneBill, we see that in that code (which works perfectly, thanks to @TelephoneBill), the values 0x300 and 0x400 were used for the pins register (PORTB_PCR0). Now looking at the K66 manual, page 221, all we can see are MUX values "Alternative X", where X goes from 1-7, and that code uses 3 and 4. So my question is: What's the relation between this MUX number and FTM channels Teensy 3.6 appear? Where can I find the association?

I can so far relate the FTMn_CHm channel from section 11.3.1, and then find that on the Teensy schematic. But then from the table to the Teensy pin is a relation I wasn't able to find.

To give an example: How to I get the pin associated with FTM3_CH0, which is connected to A5 according to the table, and to pin 2 according to the schematic of Teensy 3.6. What's the value that has to go to the PORTB register?

Thanks in advance :)
 
Last edited:
So my question is: What's the relation between this MUX number and FTM channels Teensy 3.6 appear? Where can I find the association?

It's documented in chapter 11 of the K66 reference manual, in the huge table starting on page 184.

The schematic is the quickest way to see which native K66 pins correspond to which Arduino pin numbers.

And for basic PWM usage, analogWrite() and analogWriteFrequency() are by far the simplest way... and they will be portable to future chips with different hardware. If you use the registers directly, you can access more features, but doing so comes at the cost of portability. Your code tends to be tightly tied to very specific hardware.
 
Oh, it just occurred to me now. In that table, the ALTn value corresponds to the MUX value. Now I see. That wasn't clear to me and that was my question actually. Thanks for the response, guys :)

I got that right, right? The values from that code example are taken from ALTn. So if I want FTM3_CH0, which is on pin 2, I have to use the mux value 0x400.

There's, however, another piece still missing. In TelephoneBill's code, he uses:

PORTB_PCR16 |= 0x400;
PORTB_PCR0 |= 0x300;

Now I know where the numbers 0x300 and 0x400 come from. But where did the registers PORTB_PCR0 and PORTB_PCR16 come from? How do we know that these correspond to FTM1_CH0 FTM_CLKIN0? We know from that table that they correspond to pins 16 and 0 (respectively), but the registers come from where?

About analogWrite() and analogWriteFrequency()

I'm still not sure whether everything I want to be done is doable with these wrappers (analogWrite, etc...). The reason why I believe it wouldn't be possible is because I need asynchronous clocks that match the system clock (with 0 jitter) and interrupts with that. All I saw so far with these wrappers is specific to special cases where one writes a specific frequency).

Here's what I'd like to do eventually: Is it possible to have an external signal edge trigger an interrupt function that (simply) updates an integer N, and simultaneously/asynchronously have the system clock interrupt after every N cycles (where N is continuously being updated by the other signal)? I think that should be possible to do all this with FTM, but not with these wrappers (so nothing inside `loop()`, and everything has to be within `setup()` ).

I really appreciate your help :)
 
But where did the registers PORTB_PCR0 and PORTB_PCR16 come from?

They come from chapter 12.

How do we know that these correspond to FTM1_CH0 FTM_CLKIN0?

The first 2 columns of the bit signal mux table are the chip's pin numbers. You can match those up to the schematic. Or the 3rd column is Freescale's pin name, which you can also match up to the schematic.

So for example, you can know PORTB_PCR0 is for signal "PTB0", which you'll find in the table on page 187. You can see it's BGA pin number H10. You can see on the schematic that's Arduino pin "16 / A2".

You can then look at the table to know that particular pin has these alternate functions.

Code:
ADC0_SE8/  ADC0_SE8/  PTB0/   I2C0_SCL FTM1_CH0  RMII0_MDIO/ SDRAM_   FTM1_QD_
ADC1_SE8/  ADC1_SE8/  LLWU_P5                    MII0_MDIO   CAS_b    PHA/
TSI0_CH0   TSI0_CH0                                                   TPM1_CH0
 
Here's what I'd like to do eventually: Is it possible to have an external signal edge trigger an interrupt function that (simply) updates an integer N, and simultaneously/asynchronously have the system clock interrupt after every N cycles (where N is continuously being updated by the other signal)? I think that should be possible to do all this with FTM, but not with these wrappers (so nothing inside `loop()`, and everything has to be within `setup()` ).

When you say "update integer N", that doesn't say if that's a unit increment or a decrement, or even greater amounts. It sounds like you want the system clock to be "in step" (in some way) with the frequency of the external signal. This is what I would describe as "phase lock". If the external frequency is different to that of the system clock, then some form of external multiplier or divider would be required to create an intermediate frequency which was in "phase lock".

Here is where you need to apply your imagination. And you need to have a good basic "model" of what is happening inside the FTM, such that you can imagine how the model will meet the needs of the requirement. Only you can decide if your "imagined idea" is good enough, for often it won't be, and then you tweak the idea until it fits what can be done realistically.

One form of the basic "model" of an FTM is this...

The "output compare mode" can toggle an output pin every time the FTM count reaches zero (we assume a down count mode). At which point, the interrupt will be triggered (if enabled) by the TOF (overflow flag). The "modulus value" will then be injected into the counter, so that on the following clock pulse, the count will be decremented to "modulus minus one" and the process starts over again.

Now one further feature which is extermely useful is that some external pins (say set as CH1, if the other CH0 is an output) can TRAP THE COUNT VALUE (at what ever its current value is) IMMEDIATELY THAT THE PIN TRANSITS FROM LOW TO HIGH (or vice versa - as you config it). That value is "trapped" as FTMx_C1V for CH1 - and it won't alter until you reset the event flag in FTMx_C1SC.

This trap action could very well be your variable N - for its value will be dependant on the instant that the external transition happens. It is giving you some idea of the phase relationship of the external signal w.r.t. the internal FTM clock. And the fact it has been "trapped" means that you have a little leeway to place some code somewhere (maybe in the ISR) to read it before it disappears. I normally do this early inside the ISR (save it to another variable), but after I have attended to a reset of the TOF flag.

This may not suit your requirements entirely. But it gives you some material to consider when you use your imagination.

You also mention having the system clock interrupt after N cycles. Well this sounds as if "N" is the same as the "modulus". Now you can vary the modulus dynamically, but you have to be very careful what you expect to happen (study the manual carefully). There are limits as to how you can vary the modulus dynamically. I have tried this, but have got surprising results - not always what I expected. I don't think you can guarantee what time it will take before a new modulus takes effect, for it will depend on where the count was when you changed the modulus.

I think there are other ways of implementing PWM - other than using FTM timers. I have not studied these so am not in a position to better advise. These may suit you better so do have a think about them.

Also - take care to refer to the FTM clock as the "peripheral clock" (as in the manual). The "system clock" is normally the clock for the cpu, which as you know is not the same. Paul wrote an interesting post about how the cpu (system) clock frequency and peripheral clock is derived from the 16 MHz crystal module, but I can't remember where that is. Have a search for it.
 
@PaulStoffregen Thanks a lot. I get it now. :)

@TelephoneBill That's exactly what I would like to achieve; a phase lock (is it a PLL? Not really, because it's not a feedback system). I need my interrupt calls to be phase-locked to my external signal. That N actually can change (theoretically) by any value. The ultimate purpose of this is to make the interrupt calls relative to the time defined by the external signal. Not sure whether traps will be sufficient as I don't know how that works. I'm gonna research more about that and see whether that suffices. The modulo counter is exactly what I had in mind and what I'm working on (which I got from your other code). I'm reading the manual, but it's really a lot... 150 pages to be read at least. Thanks for the ideas :)
 
Yes, it will be a PLL. And the key to your success will be the ability to adjust the feedback in a way that will respond "in time". I use the phrase "in time" because there will be a time constant associated with your feedback. If its too slow, then the controlled signal will oscillate about a mean. Getting the feedback correct is often the trick.

From a theory view, there are three types of feedback - (1) Proportional (to the error) = feedback is proportional to the amount of error; (2) Integral (the feedback is proportional to the integral of the error) = as long as an error remains, then the feedback will get bigger and bigger; (3) Differerential (the feedback is proportional to the amount of change in the error) = a constant error has no feedback amplitude at all. This theory is called "PID" control for obvious reasons. In the analogue world, you would apply a bit of feedback for each of these types of error - usually a summing amplifier with three different inputs respective to these three types of control. In the digital, I try keep it simple and just go for a proportional feedback.

I use a phase lock (of the type I think you are asking for) in my post about LORAN (see https://forum.pjrc.com/threads/45693-A-second-T31-Precision-Frequency-Standard, post #32). There is a lot in this that you can ignore, but look at the ISR and how the CH1 value is saved. I desire my phase lock to be "in lock" w.r.t. frequency, but I want a phase shift of mid way in the positive cycle from my external signal. So I make a comparison of the CH1 value of exactly half the modulus of the FTM.

Because my external signal is very "noisy", I don't just use one transition for CH1. I use 20 successive values and I store these in an array called "CH1AValue". This is stored inside the ISR. But to get the feedback, I put code in the main loop - look for the comment "//calculate the average CH1 value for pulse P1". Notice that the sum is divided by 20 to get an average value. If your external signal is "clean" then you may not need an average.

The actual feedback is later in the main loop under "//perform control if needed". Notice that here I compare the CH1Average variable against "150" - this is exactly half of the modulus of "300". I then adjust a variable called FreqAdjust by either a positive or negative amount. If you go back to the ISR you will see that FreqAdjust sets the point where I change the OSC0_CR value from being "0Ah" to being "02h" (which is changing from +10 ppm to -3ppm). I use an overall count of 1000 cycles. I let Teensy run from "0" to "FreqAdjust" at "0Ah", then I flip to use "02h" from "FreqAdjust" up to 999. So by setting FreqAdjust some where along this scale of 0 to 999, I can finely alter the overall frequency. I use a Teensy 3.1, you will need to check for a Teensy 3.6 what values may be required. Its a different 16 MHz crystal module. so likely to be not the same.

This method of using OSC0_CR gives very, very fine control - which means that the external frequency has to be pretty close to the FTM frequency in order to obtain phase lock. Your situation may not be the same. So you will have to experiment to see if this will work. Get a good digital scope to do this work - and a good signal source to make the synch trace run at the speed you desire to see the fine detail of the Teensy signal and external signal. I use a UBLOX GPS sig gen as the scope trigger while I'm experimenting - this is a good known source of timing. (See my UBlox primer post for beginners).

What I suggest you do first is try to get a "manual phase lock" - by that I mean adjust the frequency from the FTM output to be as close as you can to your external frequency manually by altering the variable that controls the frequency (in my case its FreqAdjust). If you cannot get very close with a manual adjustment, you will have no hope of doing this automatically in code.

Experiment... that is the key to success.
 
Status
Not open for further replies.
Back
Top