I got the infrared transmit logic working well now, so let me document how I got here:
There are two symbols that an IR transmitter needs to send: modulated ON (half of the carrier frequency period ON, half OFF), and OFF. The raw Pronto format contains just that, a list of burst pairs. A burst pair tells how many modulated ON symbols are followed by how many OFF symbols.
ST's application note tells us that we need to combine two specific TIM peripherals to get a modulated signal, by one timer providing a carrier frequency, and the other the bit signals (the symbol count). Unfortunately the hardware of my choice, NUCLEO-L432KC doesn't have that IR_OUT pin on the 32-pin STM32, so I had to look for another solution. When I closer examined the problem, I realized that ST's solution is over-engineered, and the same task can be achieved with a single timer, using its repetition counter.
A burst pair can be transmitted like this:
- First the modulated ON symbol count is written into the repetition counter, and the compare register is set to half the reload register, so we will get symbol count times 50% PWM output.
- As the timer's update event fires, the OFF symbol count is written to the repetition counter, and the compare register is set to 0, so we will get symbol count times no output (off).
The only problem here is that the repetition counter register is only 8 bits wide, and the Pronto format allows symbol counts on 16 bits. In practice however there is no IR protocol that would repeat the same symbol for more than 256 times. The only case of a symbol count exceeding this boundary is for the OFF symbol of the very last burst pair, in order to space out independent IR codes. At the moment I'm just limiting the last symbol count to 256, if necessary the timer's basic parameters could be reprogrammed to strictly adhere to the spacing.
Let's talk about efficiency a bit. This approach with the single timer only requires twice as many interrupt servicing as using the two timer scheme. The modified registers are configured to be preloaded, which means that the ISR has at least one carrier frequency period time to be executed, which can be appreciated if this module were integrated into a more complex design. DMA acceleration is a possibility, with a 2-register burst DMA configuration (assuming output channel 1), but that comes with a trade-off for more RAM.
I have uploaded pages of my setup and the output waveform that is captured with my logic analyzer. As I only need the transmit function to simulate IR codes for my receiver implementation, the output is active low. Conveniently I was able to map a suitable timer's output pin right next to another timer's capturing input, so all I need is a jumper to create a hardware in the loop schenario. The analyzer is hooked up to the jumper so I can cross-check the actual waveform.