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