I'm researching the possibility of using of the CMT module on Teensy 3.6 to drive a linear CCD. I determined that the easiest way is to reverse engineer the FrequencyTimer2 library, and after a bit of digging, I figured out mostly how it works. One thing bothers me though, is that while the K66 reference manual states that the primary prescaler should be used to generate a clock enable signal called intermediate frequency of approx. 8 MHz, the code in FrequencyTimer2 library appears to use the smallest primary prescaler divider possible. Given the F_BUS of 60 MHz, if the period is set to a small value, the IF will be significantly higher than the recommended 8 MHz. I wonder what is the reasoning behind the suggestion in the reference manual, and what will happen if the IF is higher than 8 MHz?
(I'm new to the teensy platform and do not have a T3.6 currently, so I cannot test this on the hardware. I'll get a T3.6 and run some tests when I get back to the States.)
Relevant excerpt from the K66 reference manual:
Relevant bits of code in the library:48.8.1 Clock divider
The CMT was originally designed to be based on an 8 MHz bus clock that could be
divided by 1, 2, 4, or 8 according to the specification. To be compatible with higher bus
frequency, the primary prescaler (PPS) was developed to receive a higher frequency and
generate a clock enable signal called intermediate frequency (IF). This IF must be
approximately equal to 8 MHz and will work as a clock enable to the secondary
prescaler. The following figure shows the clock divider block diagram.
For compatibility with previous versions of CMT, when bus clock = 8 MHz, the PPS
must be configured to zero. The PPS counter is selected according to the bus clock to
generate an intermediate frequency approximately equal to 8 MHz.
Code:void FrequencyTimer2::setPeriod(unsigned long period) { uint8_t bdiv, cdiv=0; if (period == 0) period = 1; period *= (F_BUS / 1000000); if (period < 65535*16) { bdiv = 0; } else if (period < 65535*2*16) { bdiv = 1; } else if (period < 65535*3*16) { bdiv = 2; } else if (period < 65535*4*16) { bdiv = 3; } else if (period < 65535*5*16) { bdiv = 4; } else if (period < 65535*6*16) { bdiv = 5; } else if (period < 65535*7*16) { bdiv = 6; } else if (period < 65535*8*16) { bdiv = 7; } else if (period < 65535*9*16) { bdiv = 8; } else if (period < 65535*10*16) { bdiv = 9; } else if (period < 65535*11*16) { bdiv = 10; } else if (period < 65535*12*16) { bdiv = 11; } else if (period < 65535*13*16) { bdiv = 12; } else if (period < 65535*14*16) { bdiv = 13; } else if (period < 65535*15*16) { bdiv = 14; } else if (period < 65535*16*16) { bdiv = 15; } else if (period < 65535*18*16) { bdiv = 8; cdiv = 1; } else if (period < 65535*20*16) { bdiv = 9; cdiv = 1; } else if (period < 65535*22*16) { bdiv = 10; cdiv = 1; } else if (period < 65535*24*16) { bdiv = 11; cdiv = 1; } else if (period < 65535*26*16) { bdiv = 12; cdiv = 1; } else if (period < 65535*28*16) { bdiv = 13; cdiv = 1; } else if (period < 65535*30*16) { bdiv = 14; cdiv = 1; } else if (period < 65535*32*16) { bdiv = 15; cdiv = 1; } else if (period < 65535*36*16) { bdiv = 8; cdiv = 2; } else if (period < 65535*40*16) { bdiv = 9; cdiv = 2; } else if (period < 65535*44*16) { bdiv = 10; cdiv = 2; } else if (period < 65535*48*16) { bdiv = 11; cdiv = 2; } else if (period < 65535*52*16) { bdiv = 12; cdiv = 2; } else if (period < 65535*56*16) { bdiv = 13; cdiv = 2; } else if (period < 65535*60*16) { bdiv = 14; cdiv = 2; } else if (period < 65535*64*16) { bdiv = 15; cdiv = 2; } else if (period < 65535*72*16) { bdiv = 8; cdiv = 3; } else if (period < 65535*80*16) { bdiv = 9; cdiv = 3; } else if (period < 65535*88*16) { bdiv = 10; cdiv = 3; } else if (period < 65535*96*16) { bdiv = 11; cdiv = 3; } else if (period < 65535*104*16) { bdiv = 12; cdiv = 3; } else if (period < 65535*112*16) { bdiv = 13; cdiv = 3; } else if (period < 65535*120*16) { bdiv = 14; cdiv = 3; } else { bdiv = 15; cdiv = 3; } period /= (bdiv + 1); period >>= (cdiv + 4); if (period > 65535) period = 65535; // high time = (CMD1:CMD2 + 1) ÷ (fCMTCLK ÷ 8) // low time = CMD3:CMD4 ÷ (fCMTCLK ÷ 8) SIM_SCGC4 |= SIM_SCGC4_CMT; CMT_MSC = 0; CMT_PPS = bdiv; CMT_CMD1 = ((period - 1) >> 8) & 255; CMT_CMD2 = (period - 1) & 255; CMT_CMD3 = (period >> 8) & 255; CMT_CMD4 = period & 255; CMT_OC = 0x60; CMT_MSC = (cdiv << 5) | 0x0B; // baseband mode }