]> vault307.fbx.one Git - micorpython_ir.git/blob - ir_rx/philips.py
Receiver now a package.
[micorpython_ir.git] / ir_rx / philips.py
1 # philips.py Decoder for IR remote control using synchronous code
2 # Supports Philips RC-5 RC-6 mode 0 protocols.
3
4 # Author: Peter Hinch
5 # Copyright Peter Hinch 2020 Released under the MIT license
6
7 from utime import ticks_us, ticks_diff
8 from ir_rx import IR_RX
9
10 class RC5_IR(IR_RX):
11 def __init__(self, pin, callback, *args):
12 # Block lasts <= 30ms and has <= 28 edges
13 super().__init__(pin, 28, 30, callback, *args)
14
15 def decode(self, _):
16 try:
17 nedges = self.edge # No. of edges detected
18 if not 14 <= nedges <= 28:
19 raise RuntimeError(self.OVERRUN if nedges > 28 else self.BADSTART)
20 # Regenerate bitstream
21 bits = 0
22 bit = 1
23 for x in range(1, nedges):
24 width = ticks_diff(self._times[x], self._times[x - 1])
25 if not 500 < width < 2000:
26 raise RuntimeError(self.BADBLOCK)
27 for _ in range(1 if width < 1334 else 2):
28 bits <<= 1
29 bits |= bit
30 bit ^= 1
31 self.verbose and print(bin(bits)) # Matches inverted scope waveform
32 # Decode Manchester code
33 x = 30
34 while not bits >> x:
35 x -= 1
36 m0 = 1 << x # Mask MS two bits (always 01)
37 m1 = m0 << 1
38 v = 0 # 14 bit bitstream
39 for _ in range(14):
40 v <<= 1
41 b0 = (bits & m0) > 0
42 b1 = (bits & m1) > 0
43 if b0 == b1:
44 raise RuntimeError(self.BADBLOCK)
45 v |= b0
46 m0 >>= 2
47 m1 >>= 2
48 # Split into fields (val, addr, ctrl)
49 val = (v & 0x3f) | (0x40 if ((v >> 12) & 1) else 0)
50 addr = (v >> 6) & 0x1f
51 ctrl = (v >> 11) & 1
52
53 except RuntimeError as e:
54 val, addr, ctrl = e.args[0], 0, 0
55 # Set up for new data burst and run user callback
56 self.do_callback(val, addr, ctrl)
57
58 class RC6_M0(IR_RX):
59 # Even on Pyboard D the 444μs nominal pulses can be recorded as up to 705μs
60 # Scope shows 360-520 μs (-84μs +76μs relative to nominal)
61 # Header nominal 2666, 889, 444, 889, 444, 444, 444, 444 carrier ON at end
62 hdr = ((1800, 4000), (593, 1333), (222, 750), (593, 1333), (222, 750), (222, 750), (222, 750), (222, 750))
63 def __init__(self, pin, callback, *args):
64 # Block lasts 23ms nominal and has <=44 edges
65 super().__init__(pin, 44, 30, callback, *args)
66
67 def decode(self, _):
68 try:
69 nedges = self.edge # No. of edges detected
70 if not 22 <= nedges <= 44:
71 raise RuntimeError(self.OVERRUN if nedges > 28 else self.BADSTART)
72 for x, lims in enumerate(self.hdr):
73 width = ticks_diff(self._times[x + 1], self._times[x])
74 if not (lims[0] < width < lims[1]):
75 self.verbose and print('Bad start', x, width, lims)
76 raise RuntimeError(self.BADSTART)
77 x += 1
78 width = ticks_diff(self._times[x + 1], self._times[x])
79 # 2nd bit of last 0 is 444μs (0) or 1333μs (1)
80 if not 222 < width < 1555:
81 self.verbose and print('Bad block 1 Width', width, 'x', x)
82 raise RuntimeError(self.BADBLOCK)
83 short = width < 889
84 v = int(not short)
85 bit = v
86 bits = 1 # Bits decoded
87 x += 1 + int(short)
88 width = ticks_diff(self._times[x + 1], self._times[x])
89 if not 222 < width < 1555:
90 self.verbose and print('Bad block 2 Width', width, 'x', x)
91 raise RuntimeError(self.BADBLOCK)
92 short = width < 1111
93 if not short:
94 bit ^= 1
95 x += 1 + int(short) # If it's short, we know width of next
96 v <<= 1
97 v |= bit # MSB of result
98 bits += 1
99 # Decode bitstream
100 while bits < 17:
101 # -1 convert count to index, -1 because we look ahead
102 if x > nedges - 2:
103 raise RuntimeError(self.BADBLOCK)
104 # width is 444/889 nominal
105 width = ticks_diff(self._times[x + 1], self._times[x])
106 if not 222 < width < 1111:
107 self.verbose and print('Bad block 3 Width', width, 'x', x)
108 raise RuntimeError(self.BADBLOCK)
109 short = width < 666
110 if not short:
111 bit ^= 1
112 v <<= 1
113 v |= bit
114 bits += 1
115 x += 1 + int(short)
116
117 if self.verbose:
118 ss = '20-bit format {:020b} x={} nedges={} bits={}'
119 print(ss.format(v, x, nedges, bits))
120
121 val = v & 0xff
122 addr = (v >> 8) & 0xff
123 ctrl = (v >> 16) & 1
124 except RuntimeError as e:
125 val, addr, ctrl = e.args[0], 0, 0
126 # Set up for new data burst and run user callback
127 self.do_callback(val, addr, ctrl)