X-Git-Url: https://vault307.fbx.one/gitweb/micorpython_ir.git/blobdiff_plain/3bc46448ddca0bfdf3a98d96c3e9315159bf642b..3b6cfaf15ad930c34b0d7f87c6a841ea651ccccb:/ir_rx/philips.py?ds=sidebyside diff --git a/ir_rx/philips.py b/ir_rx/philips.py new file mode 100644 index 0000000..cbd96f8 --- /dev/null +++ b/ir_rx/philips.py @@ -0,0 +1,127 @@ +# philips.py Decoder for IR remote control using synchronous code +# Supports Philips RC-5 RC-6 mode 0 protocols. + +# Author: Peter Hinch +# Copyright Peter Hinch 2020 Released under the MIT license + +from utime import ticks_us, ticks_diff +from ir_rx import IR_RX + +class RC5_IR(IR_RX): + def __init__(self, pin, callback, *args): + # Block lasts <= 30ms and has <= 28 edges + super().__init__(pin, 28, 30, callback, *args) + + def decode(self, _): + try: + nedges = self.edge # No. of edges detected + if not 14 <= nedges <= 28: + raise RuntimeError(self.OVERRUN if nedges > 28 else self.BADSTART) + # Regenerate bitstream + bits = 0 + bit = 1 + for x in range(1, nedges): + width = ticks_diff(self._times[x], self._times[x - 1]) + if not 500 < width < 2000: + raise RuntimeError(self.BADBLOCK) + for _ in range(1 if width < 1334 else 2): + bits <<= 1 + bits |= bit + bit ^= 1 + self.verbose and print(bin(bits)) # Matches inverted scope waveform + # Decode Manchester code + x = 30 + while not bits >> x: + x -= 1 + m0 = 1 << x # Mask MS two bits (always 01) + m1 = m0 << 1 + v = 0 # 14 bit bitstream + for _ in range(14): + v <<= 1 + b0 = (bits & m0) > 0 + b1 = (bits & m1) > 0 + if b0 == b1: + raise RuntimeError(self.BADBLOCK) + v |= b0 + m0 >>= 2 + m1 >>= 2 + # Split into fields (val, addr, ctrl) + val = (v & 0x3f) | (0x40 if ((v >> 12) & 1) else 0) + addr = (v >> 6) & 0x1f + ctrl = (v >> 11) & 1 + + except RuntimeError as e: + val, addr, ctrl = e.args[0], 0, 0 + # Set up for new data burst and run user callback + self.do_callback(val, addr, ctrl) + +class RC6_M0(IR_RX): + # Even on Pyboard D the 444μs nominal pulses can be recorded as up to 705μs + # Scope shows 360-520 μs (-84μs +76μs relative to nominal) + # Header nominal 2666, 889, 444, 889, 444, 444, 444, 444 carrier ON at end + hdr = ((1800, 4000), (593, 1333), (222, 750), (593, 1333), (222, 750), (222, 750), (222, 750), (222, 750)) + def __init__(self, pin, callback, *args): + # Block lasts 23ms nominal and has <=44 edges + super().__init__(pin, 44, 30, callback, *args) + + def decode(self, _): + try: + nedges = self.edge # No. of edges detected + if not 22 <= nedges <= 44: + raise RuntimeError(self.OVERRUN if nedges > 28 else self.BADSTART) + for x, lims in enumerate(self.hdr): + width = ticks_diff(self._times[x + 1], self._times[x]) + if not (lims[0] < width < lims[1]): + self.verbose and print('Bad start', x, width, lims) + raise RuntimeError(self.BADSTART) + x += 1 + width = ticks_diff(self._times[x + 1], self._times[x]) + # 2nd bit of last 0 is 444μs (0) or 1333μs (1) + if not 222 < width < 1555: + self.verbose and print('Bad block 1 Width', width, 'x', x) + raise RuntimeError(self.BADBLOCK) + short = width < 889 + v = int(not short) + bit = v + bits = 1 # Bits decoded + x += 1 + int(short) + width = ticks_diff(self._times[x + 1], self._times[x]) + if not 222 < width < 1555: + self.verbose and print('Bad block 2 Width', width, 'x', x) + raise RuntimeError(self.BADBLOCK) + short = width < 1111 + if not short: + bit ^= 1 + x += 1 + int(short) # If it's short, we know width of next + v <<= 1 + v |= bit # MSB of result + bits += 1 + # Decode bitstream + while bits < 17: + # -1 convert count to index, -1 because we look ahead + if x > nedges - 2: + raise RuntimeError(self.BADBLOCK) + # width is 444/889 nominal + width = ticks_diff(self._times[x + 1], self._times[x]) + if not 222 < width < 1111: + self.verbose and print('Bad block 3 Width', width, 'x', x) + raise RuntimeError(self.BADBLOCK) + short = width < 666 + if not short: + bit ^= 1 + v <<= 1 + v |= bit + bits += 1 + x += 1 + int(short) + + if self.verbose: + ss = '20-bit format {:020b} x={} nedges={} bits={}' + print(ss.format(v, x, nedges, bits)) + + val = v & 0xff + addr = (v >> 8) & 0xff + ctrl = (v >> 16) & 1 + except RuntimeError as e: + val, addr, ctrl = e.args[0], 0, 0 + # Set up for new data burst and run user callback + self.do_callback(val, addr, ctrl)