]> vault307.fbx.one Git - micorpython_ir.git/blob - ir_rx/nec.py
Receiver now a package.
[micorpython_ir.git] / ir_rx / nec.py
1 # nec.py Decoder for IR remote control using synchronous code
2 # Supports NEC protocol.
3 # For a remote using NEC see https://www.adafruit.com/products/389
4
5 # Author: Peter Hinch
6 # Copyright Peter Hinch 2020 Released under the MIT license
7
8 from utime import ticks_us, ticks_diff
9 from ir_rx import IR_RX
10
11 class NEC_ABC(IR_RX):
12 def __init__(self, pin, extended, callback, *args):
13 # Block lasts <= 80ms (extended mode) and has 68 edges
14 super().__init__(pin, 68, 80, callback, *args)
15 self._extended = extended
16 self._addr = 0
17
18 def decode(self, _):
19 try:
20 if self.edge > 68:
21 raise RuntimeError(self.OVERRUN)
22 width = ticks_diff(self._times[1], self._times[0])
23 if width < 4000: # 9ms leading mark for all valid data
24 raise RuntimeError(self.BADSTART)
25 width = ticks_diff(self._times[2], self._times[1])
26 if width > 3000: # 4.5ms space for normal data
27 if self.edge < 68: # Haven't received the correct number of edges
28 raise RuntimeError(self.BADBLOCK)
29 # Time spaces only (marks are always 562.5µs)
30 # Space is 1.6875ms (1) or 562.5µs (0)
31 # Skip last bit which is always 1
32 val = 0
33 for edge in range(3, 68 - 2, 2):
34 val >>= 1
35 if ticks_diff(self._times[edge + 1], self._times[edge]) > 1120:
36 val |= 0x80000000
37 elif width > 1700: # 2.5ms space for a repeat code. Should have exactly 4 edges.
38 raise RuntimeError(self.REPEAT if self.edge == 4 else self.BADREP) # Treat REPEAT as error.
39 else:
40 raise RuntimeError(self.BADSTART)
41 addr = val & 0xff # 8 bit addr
42 cmd = (val >> 16) & 0xff
43 if cmd != (val >> 24) ^ 0xff:
44 raise RuntimeError(self.BADDATA)
45 if addr != ((val >> 8) ^ 0xff) & 0xff: # 8 bit addr doesn't match check
46 if not self._extended:
47 raise RuntimeError(self.BADADDR)
48 addr |= val & 0xff00 # pass assumed 16 bit address to callback
49 self._addr = addr
50 except RuntimeError as e:
51 cmd = e.args[0]
52 addr = self._addr if cmd == self.REPEAT else 0 # REPEAT uses last address
53 # Set up for new data burst and run user callback
54 self.do_callback(cmd, addr, 0, self.REPEAT)
55
56 class NEC_8(NEC_ABC):
57 def __init__(self, pin, callback, *args):
58 super().__init__(pin, False, callback, *args)
59
60 class NEC_16(NEC_ABC):
61 def __init__(self, pin, callback, *args):
62 super().__init__(pin, True, callback, *args)