Search This Blog

Wednesday, August 1, 2018

Audio sw - NEC IR Remote Protocol

 Projects / Audio Switching  Original post date: 07/29/2016

After a lot of procrastination, I have settled on the IR Remote protocol and device to be used for this project. The tricky part is to find one that I don't have. :P I use my hacker friendly "All for One" URC-8017 Universal remote control to program in a new device.

NEC protocol is popular and the clear winner as the standard allows for an 8-bit address and 8-bit command. Four bytes of data are transmitted. There are 2 for the address field and 2 for the command. The second in the pair is the one's complement. There is a newer "NEC2" extension which uses a similar format, but both bytes for a 16-bit address. This is the protocol used in my TV.

I use timer 14 and Input Capture with both rising and falling edge triggered IRQ to measure the pulse width. The IRQ code reads off the current logic level of the pin from the GPIO port IDR (Input Data Register) and figure which edge it is at.

Inside the IRQ service routine is a state machine that checks the pulse widths and keep tracks of the bit number. The code allows for timing variation such as crystal/resonator tolerances, rise/fall time of IR receiver on weak signal etc. The received data is checked against the complement field(s) and buffered in a FIFO queue.


The code needs some more polishing and it is going to take a bit of work to make a user interface and a way of storing the setting for this project. Until then, I don't have an easy way to set the time on the RTC. That's why the time is always unset in the screenshots and demos.

I found a couple of obscure bugs with my existing code. One of them was a race condition for a new DMA polling loop. The new code puts the ARM core into sleep mode while waiting for the LCD DMA to finish.


Because the firmware have multiple IRQ, a shared flag variable, SPI_Wait, from the DMA IRQ service routine is to indicate that the DMA is done. The SPI_Wait was set in SPI_DMA_Wait() previously. Once in a while, DMA managed to fill the SPI FIFO and triggered the IRQ before SPI_DMA_Wait() get called. Thanks to the debugger, I found the issue. Now I set SPI_Wait prior to enabling the DMA.

5 hours later and it still works, so I guess this is fixed.

The other bug was the array indexing for plotting the spectrum was out of bound. One of the #define symbols was incorrectly used to find the upper bound of the rendering loop. The new code uses more RAM, so that memory index is now pointing at non-zeroed and it showed up in the plot as a spike.

Editorial note: This code was ported to STM8.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.