Yichi_Yang
New member
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:
(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:
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.
Relevant bits of code in the library:
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
}
Last edited: