Implementing infrared functions on UART0 with FRDM-KE02Z platform. This document shows the implementation of the infrared on the UART0 using the FRDM-KE02Z platform. The FRDM-KE02Z platform is a developing platform for rapid prototyping. The board has a MKE02Z64VQH2 MCU a Kinetis E series MCU which is the first 5-Volt MCU built on the ARM Cortex-M0+ core. You can check the evaluation board in the Freescale’s webpage (FRDM-KE02Z: Kinetis E Series Freedom Development Platform) The Freedom Board has a lot of great features and one of this is an IrDA transmitter and receiver on it. Check this out! One of the features of the MCU is that the UART0 module can implement Infrared functions just following some tricks (MCU-magic tricks). According to the Reference Manual (Document Number: MKE02Z64M20SF0RM) this tricks are: UART0_TX modulation: UART0_TX output can be modulated by FTM0 channel 0 PWM output UART0_RX Tag: UART0_RX input can be tagged to FTM0 channel 1 or filtered by ACMP0 module For this example we are going to use the ACMP0 module to implement the UART0_RX functionality. Note1: The Core is configured to run at the maximum frequency: 20 Mhz Note2: Refer to the reference manual document for more information about the registers. Configuring the FTM0. The next lines show the configuration of the FTM0; the module is configured with a Frequency of 38 KHz which is the ideal frequency for an infrared led. The FTM0_CH0 is in Edge_Aligned PWM mode (EPWM). #define IR_FREQUENCY 38000 //hz #define FTM0_CLOCK BUS_CLK_HZ #define FTM0_MOD_VALUE FTM0_CLOCK/IR_FREQUENCY #define FTM0_C0V_VALUE FTM0_MOD_VALUE/2 void FTM0CH0_Init( void ) { SIM_SCGC |= SIM_SCGC_FTM0_MASK; // Init FTM0 to PWM output,frequency is 38khz FTM0_MOD= FTM0_MOD_VALUE; FTM0_C0SC = 0x28; FTM0_C0V = FTM0_C0V_VALUE; FTM0_SC = 0x08; // bus clock divide by 2 } With this we accomplish the UART0_TX modulation through a PWM on the FTM0_CH0. Configuring the ACMP0. The configuration of the ACMP0 is using a DAC and allowing the ACMP0 can be driven by an analog input. void ACMP_Init ( void ) { SIM_SCGC |= SIM_SCGC_ACMP0_MASK; ACMP0_C1 |= ACMP_C1_DACEN_MASK | ACMP_C1_DACREF_MASK| ACMP_C1_DACVAL(21); // enable DAC ACMP0_C0 |= ACMP_C0_ACPSEL(0x03)| ACMP_C0_ACNSEL(0x01); ACMP0_C2 |= ACMP_C2_ACIPE(0x02); // enable ACMP1 connect to PIN ACMP0_CS |= ACMP_CS_ACE_MASK; // enable ACMP } With this we have now implemented the UART0_RX. IrDA initialization. Now the important thing is to initialize the UART0 to work together with these tricks and implement the irDA functions. Basically we initialize the UART0 like when we use normal serial communication (this is not the topic of this post, refer to the project to see the UART_init function) and we write to the most important registers: SIM_SOPT |= SIM_SOPT_RXDFE_MASK; UART0_RX input signal is filtered by ACMP, then injected to UART0. SIM_SOPT |= SIM_SOPT_TXDME_MASK; UART0_TX output is modulated by FTM0 channel 0 before mapped to pinout. The configuration is as follows: void IrDA_Init( void ) { // initialize UART0, 2400 baudrate UART_init(UART0_BASE_PTR,BUS_CLK_HZ/1000,2400); // clear RDRF flag UART0_S1 |= UART_S1_RDRF_MASK; // initialize FTM0CH1 as 38k PWM output FTM0CH0_Init(); // enable ACMP ACMP_Init(); SIM_SOPT |= SIM_SOPT_RXDFE_MASK; //UART0_RX input signal is filtered by ACMP, then injected to UART0. UART0_S2 &= ~UART_S2_RXINV_MASK; //inverse data input SIM_SOPT |= SIM_SOPT_TXDME_MASK; //UART0_TX output is modulated by FTM0 channel 0 before mapped to pinout. } With the irDA initialization we got the infrared features on the UART0. Philosophy of the Example In the attachments of this post you can find the example which shows the use of these functions in a basic application; the project was compiled in CodeWarrior 10.6 and the philosophy is: I hope that the information presented on this document could be useful for you. Thank you! Best Regards! Freedom Development Platform Kinetis E Series MCUs Re: Implementing infrared functions on UART0 with FRDM-KE02Z platform. I figured out what was the problem. The TWR-K60 has a different IR receiver filter with R=1KOhm and C=0.1uF, which passes frequencies less than 1.6KHz compared to the FRDM-KE02Z which has R=1KOhm and C=1000PF, which will passes frequencies less than 160KHz, hence 38KHz is OK for that board. 38KHz wont work with TWR-K60N512 because it wi ll be blocked by the filter. I set the UART0 baud lower to 1400 and the FTM1 frequency to 1.5KHz and it works like a charm! I compared the two user manuals 🙂 Formula: fc = 1/(2*pi*Τ) = 1/(2pi*RC); where R=1000Ohms, C=0.1*10^-6Farads fc = 1.6KHz Re: Implementing infrared functions on UART0 with FRDM-KE02Z platform. I got it to work without FTM modulation, just with the 3/16 narrow pulse. UART0 configured with 2400 baudrate and inverted RX, CMP DAC Output voltage select is (Vin/64)*31+1 = VDD(3.3v) * 0.5 = 1.65V for a high(1), supply voltage select is 1 for Vin2 which is VDD (3.3v). The trick is to configure the Comparator properly with a good reference voltage on the inverting input. I did not configure any sampling. Next I will try with FTM modulation, only I dont know how exactly to demodulate on the comparator end using the sampling feature. Re: Implementing infrared functions on UART0 with FRDM-KE02Z platform. I am trying this with the TWR-K60N512 KIT, I can receive interrupts on UART0_Rx through Comparator from a TV remote signal, but not from the Tx pin although checking with a smartphone camera, the Tx IR signal is going on. The code is as follows: #include "types.h" #include "infrared.h" #define IR_FREQUENCY 38000 #define FTM1_CLOCK 750000 #define FTM1_MOD_VALUE FTM1_CLOCK/IR_FREQUENCY #define FTM1_C0V_VALUE FTM1_MOD_VALUE/2 void init_infrared(void){ //initialize uart0 as infrared port through CMP0 init_uart0(); //initialize Comparator init_cmp0(); //initialize the Flex timer init_ftm(); } void init_uart(UART_MemMapPtr uartch, int sysclk, int baud){ uint16_t ubd, temp, brfa; //disable Tx and Rx during setup UART_C2_REG(uartch) &= ~(UART_C2_TE_MASK | UART_C2_RE_MASK ); /* Configure the UART for 8-bit mode, no parity */ /* We need all default settings, so entire register is cleared */ UART_C1_REG(uartch) = 0; /* Calculate baud settings */ ubd = (uint16_t)((sysclk*1000)/(baud * 16)); /* Save off the current value of the UARTx_BDH except for the SBR */ temp = UART_BDH_REG(uartch) & ~(UART_BDH_SBR(0x1F)); UART_BDH_REG(uartch) = temp | UART_BDH_SBR(((ubd & 0x1F00) >> 8)); UART_BDL_REG(uartch) = (uint8_t)(ubd & UART_BDL_SBR_MASK); /* Determine if a fractional divider is needed to get closer to the baud rate */ brfa = (((sysclk*32000)/(baud * 16)) - (ubd * 32)); /* Save off the current value of the UARTx_C4 register except for the BRFA */ temp = UART_C4_REG(uartch) & ~(UART_C4_BRFA(0x1F)); UART_C4_REG(uartch) = temp | UART_C4_BRFA(brfa); // enable the reciever interrupts UART_C2_REG(uartch) |= UART_C2_RIE_MASK; } void init_uart0(void){ //Gate clock to uart0 SIM_SCGC4 |= SIM_SCGC4_UART0_MASK; init_uart(UART0_BASE_PTR,96000,2400);//core clock is 96Mhz=96000Khz //enable IR encoding and decoding UART0_IR |= UART_IR_IREN_MASK; UART0_IR |= UART_IR_TNP(0x0);//narrow pulse 3/16 of baudrate //System integration to route UART0_RX to CMP0 SIM_SOPT5 |= SIM_SOPT5_UART0RXSRC(01);//CMP0 as source of UART0_RX SIM_SOPT5 |= SIM_SOPT5_UART0TXSRC(01);//Tx pin modulated with FTM1 channel0 output SIM_SOPT2 |= SIM_SOPT2_CMTUARTPAD_MASK;//select dual pad drive strength for UART0_TX //Enable receiver and transmitter UART0_C2 |= UART_C2_RE_MASK; UART0_C2 |= UART_C2_TE_MASK; // configure Nested Vector Interrupt Controller: clear pending and set enable NVICICPR1 |= interrupt_mask(1,INT_UART0_RX_TX); NVICISER1 |= interrupt_mask(1,INT_UART0_RX_TX); } //UART0 brief interrupt handler void UART0_RX_TX_IRQHandler(){ if((UART0_S1 & UART_S1_RDRF_MASK)==UART_S1_RDRF_MASK){ byte2 = (uint8_t)UART0_D; data_available2=1; } } //FTM1 initialization, used to modulate UART0_TX void init_ftm(void){ SIM_SCGC6 |= SIM_SCGC6_FTM1_MASK;//gate the clock FTM1_SC |= FTM_SC_CLKS(01);//system core clock as clock source FTM1_SC |= FTM_SC_PS(7);//divide system clock by 128 = 750Khz FTM1_MODE |= FTM_MODE_WPDIS_MASK;//disable write protect FTM1_MOD |= FTM_MOD_MOD(FTM1_MOD_VALUE);//modulo value FTM1_C0SC = 0x28;//edge-aligned PWM FTM1_C0V = FTM1_C0V_VALUE; } void init_cmp0(void){ //gate the clock to CMP SIM_SCGC4 |= SIM_SCGC4_CMP_MASK; //disable comparator while configuring CMP0_CR1 &= ~(CMP_CR1_OPE_MASK | CMP_CR1_EN_MASK); //Configure and enable the Comparator's DAC for reference voltage CMP0_DACCR |= CMP_DACCR_VRSEL_MASK;//supply voltage select is 1 for Vin2 CMP0_DACCR |= CMP_DACCR_VOSEL(0x0F);//Output voltage select is (Vin/64)*VOSEL+1 = Vin * 0.5 for a high(1) CMP0_DACCR |= CMP_DACCR_DACEN_MASK; //enable PMUX and MMUX CMP0_MUXCR |= CMP_MUXCR_PEN_MASK | CMP_MUXCR_MEN_MASK; //select IN0 for PMUX(positive side) and DACOUT i.e channel 7 as MMUX(minus side) // |\ // IN0---|+\ // | \______CMP_OUT // | / // DACout---|-/ // |/ // COMPARATOR // CMP0_MUXCR |= CMP_MUXCR_PSEL(0); CMP0_MUXCR |= CMP_MUXCR_MSEL(7); //set 0 samples per measurement CMP0_CR0 |= CMP_CR0_FILTER_CNT(0x0);//disable filter CMP0_CR1 |= CMP_CR1_COS_MASK;//unfiltered output CMP0_CR1 |= CMP_CR1_INV_MASK;//invert output //enable comparator and the output pin CMP0_CR1 |= (CMP_CR1_OPE_MASK | CMP_CR1_EN_MASK); } I think I am missing some information on how the modulation actually works. Could you please explain a little further on the actual protocol, how the timing diagrams look like, how do we demodulate, where are the UART settings for demodulation, i can see how we modulate with the FTM, but not how we are actually demodulating the received signal. Is it by sampling the CMP input? BlackNight you have any ideas? Re: Implementing infrared functions on UART0 with FRDM-KE02Z platform. Hello Sanchez, A good post indeed. But, I was wondering what might be the communication pattern? Is it a standard 3/16th bit width communication or the modulated Tx waveform looks different altogether? Couldn't capture on oscilloscope as the FTM is running continuously. Is the modulated waveform similar to the one attached?
View full article