# nec.py Decoder for IR remote control using synchronous code # Supports NEC protocol. # For a remote using NEC see https://www.adafruit.com/products/389 # Author: Peter Hinch # Copyright Peter Hinch 2020 Released under the MIT license from utime import ticks_us, ticks_diff from stm32_ir_receiver import IR_RX class NEC_ABC(IR_RX): def __init__(self, pin, extended, callback, *args): # Block lasts <= 80ms (extended mode) and has 68 edges super().__init__(pin, 68, 80, callback, *args) self._extended = extended self._addr = 0 def decode(self, _): try: if self.edge > 68: raise RuntimeError(self.OVERRUN) width = ticks_diff(self._times[1], self._times[0]) if width < 4000: # 9ms leading mark for all valid data raise RuntimeError(self.BADSTART) width = ticks_diff(self._times[2], self._times[1]) if width > 3000: # 4.5ms space for normal data if self.edge < 68: # Haven't received the correct number of edges raise RuntimeError(self.BADBLOCK) # Time spaces only (marks are always 562.5µs) # Space is 1.6875ms (1) or 562.5µs (0) # Skip last bit which is always 1 val = 0 for edge in range(3, 68 - 2, 2): val >>= 1 if ticks_diff(self._times[edge + 1], self._times[edge]) > 1120: val |= 0x80000000 elif width > 1700: # 2.5ms space for a repeat code. Should have exactly 4 edges. raise RuntimeError(self.REPEAT if self.edge == 4 else self.BADREP) # Treat REPEAT as error. else: raise RuntimeError(self.BADSTART) addr = val & 0xff # 8 bit addr cmd = (val >> 16) & 0xff if cmd != (val >> 24) ^ 0xff: raise RuntimeError(self.BADDATA) if addr != ((val >> 8) ^ 0xff) & 0xff: # 8 bit addr doesn't match check if not self._extended: raise RuntimeError(self.BADADDR) addr |= val & 0xff00 # pass assumed 16 bit address to callback self._addr = addr except RuntimeError as e: cmd = e.args[0] addr = self._addr if cmd == self.REPEAT else 0 # REPEAT uses last address # Set up for new data burst and run user callback self.do_callback(cmd, addr, 0, self.REPEAT) class NEC_8(NEC_ABC): def __init__(self, pin, callback, *args): super().__init__(pin, False, callback, *args) class NEC_16(NEC_ABC): def __init__(self, pin, callback, *args): super().__init__(pin, True, callback, *args)