]> vault307.fbx.one Git - micorpython_ir.git/commitdiff
Prior to RC6 rx redesign.
authorPeter Hinch <peter@hinch.me.uk>
Tue, 25 Feb 2020 06:55:03 +0000 (06:55 +0000)
committerPeter Hinch <peter@hinch.me.uk>
Tue, 25 Feb 2020 06:55:03 +0000 (06:55 +0000)
ir_rx.py
ir_rx_test.py
ir_tx.py
ir_tx_test.py

index 6f20b2b0a61f941a1ab77b346150beba884b3c23..896d9cdb4c5269931d90e77baf040dae509a1102 100644 (file)
--- a/ir_rx.py
+++ b/ir_rx.py
@@ -166,7 +166,9 @@ class RC5_IR(IR_RX):
         self.callback(val, addr, ctrl, *self.args)
 
 class RC6_M0(IR_RX):
         self.callback(val, addr, ctrl, *self.args)
 
 class RC6_M0(IR_RX):
-    # Even on Pyboard D these 444us nominal pulses can be recorded as up to 705us
+    # 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
     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
@@ -179,43 +181,47 @@ class RC6_M0(IR_RX):
                 raise RuntimeError(OVERRUN if nedges > 28 else BADSTART)
             for x, lims in enumerate(self.hdr):
                 width = ticks_diff(self._times[x + 1], self._times[x])
                 raise RuntimeError(OVERRUN if nedges > 28 else BADSTART)
             for x, lims in enumerate(self.hdr):
                 width = ticks_diff(self._times[x + 1], self._times[x])
+                #print('x = {}, width = {}, lims = {}'.format(x, width, lims))
                 if not (lims[0] < width < lims[1]):
                 if not (lims[0] < width < lims[1]):
-                    print('Bad start', x, width, lims)
+                    #print('Bad start', x, width, lims)
                     raise RuntimeError(BADSTART)
             x += 1
             width = ticks_diff(self._times[x + 1], self._times[x])
                     raise RuntimeError(BADSTART)
             x += 1
             width = ticks_diff(self._times[x + 1], self._times[x])
-            ctrl = width > 889  # Long bit
-            start = x + 2  # Skip 2nd long bit
+            # Long bit is 889μs (0) or 1333μs (1)
+            ctrl = width > 1111  # If 1333, ctrl == True and carrier is off
+            start = x + 2 if ctrl else x + 3 # Skip 2nd long bit
 
             # Regenerate bitstream
 
             # Regenerate bitstream
-            bits = 0
-            bit = 0
-            for x in range(start, nedges):
-                width = ticks_diff(self._times[x], self._times[x - 1])
+            bits = 1  # MSB is a dummy 1 to mark start of bitstream
+            bit = int(ctrl)
+            for x in range(start, nedges - 1):
+                width = ticks_diff(self._times[x + 1], self._times[x])
                 if not 222 < width < 1333:
                 if not 222 < width < 1333:
-                    print('Width', width)
+                    #print('Width', width, 'x', x)
                     raise RuntimeError(BADBLOCK)
                 for _ in range(1 if width < 666 else 2):
                     bits <<= 1
                     bits |= bit
                 bit ^= 1
                     raise RuntimeError(BADBLOCK)
                 for _ in range(1 if width < 666 else 2):
                     bits <<= 1
                     bits |= bit
                 bit ^= 1
-            print(bin(bits), len(bin(bits)) - 2)
+            print('36-bit format {:036b} x={} nedges={}'.format(bits, x, nedges))
 
 
-            # Decode Manchester code
-            x = 32
+            # Decode Manchester code. Bitstream varies in length: find MS 1.
+            x = 36
             while not bits >> x:
                 x -= 1
             while not bits >> x:
                 x -= 1
-            m0 = 1 << (x - 1)
-            m1 = 1 << x  # MSB of pair
+            # Now points to dummy 1
+            x -= 2  # Point to MS biphase pair
+            m0 = 1 << x
+            m1 = m0 << 1  # MSB of pair
             v = 0  # 16 bit bitstream
             for _ in range(16):
                 v <<= 1
                 b0 = (bits & m0) > 0
                 b1 = (bits & m1) > 0
             v = 0  # 16 bit bitstream
             for _ in range(16):
                 v <<= 1
                 b0 = (bits & m0) > 0
                 b1 = (bits & m1) > 0
-                #print(int(b1), int(b0))
+                print(int(b1), int(b0))
                 if b0 == b1:
                     raise RuntimeError(BADBLOCK)
                 if b0 == b1:
                     raise RuntimeError(BADBLOCK)
-                v |= b0
+                v |= b1
                 m0 >>= 2
                 m1 >>= 2
             # Split into fields (val, addr)
                 m0 >>= 2
                 m1 >>= 2
             # Split into fields (val, addr)
index 908d23f83cb229e29f2610bba9971a2ec417b0ac..401c077eae6d5ec3e4a90f55770f9be5906e0b03 100644 (file)
@@ -9,7 +9,7 @@
 from sys import platform
 import time
 from machine import Pin, freq
 from sys import platform
 import time
 from machine import Pin, freq
-from arem import *
+from ir_rx import *
 
 ESP32 = platform == 'esp32' or platform == 'esp32_LoBo'
 
 
 ESP32 = platform == 'esp32' or platform == 'esp32_LoBo'
 
index 97578407f391b9469929c168336c81db647033ca..0697d9a1cdd9a6541f70dc0d8881501fe4158f3e 100644 (file)
--- a/ir_tx.py
+++ b/ir_tx.py
@@ -26,39 +26,41 @@ _T_RC6 = const(444)
 _T2_RC6 = const(889)
 
 # IR abstract base class. Array holds periods in μs between toggling 36/38KHz
 _T2_RC6 = const(889)
 
 # IR abstract base class. Array holds periods in μs between toggling 36/38KHz
-# carrier on or off.
-# Subclass is responsible for populating .arr and initiating transmission.
-# Operation is in two phases: .transmit populates .arr with times in μs, then
-# calls .start to initiate physical transmission.
+# carrier on or off. Physical transmission occurs in an ISR context controlled
+# by timer 2 and timer 5.
+# Operation is in two phases: .transmit populates .arr with times in μs (via
+# subclass), then initiates physical transmission.
 class IR:
 
 class IR:
 
-    def __init__(self, pin, freq, asize, duty):
-        tim = Timer(2, freq=freq)
+    def __init__(self, pin, freq, asize, duty, verbose):
+        tim = Timer(2, freq=freq)  # Timer 2/pin produces 36/38KHz carrier
         self._ch = tim.channel(1, Timer.PWM, pin=pin)
         self._ch = tim.channel(1, Timer.PWM, pin=pin)
-        self._ch.pulse_width_percent(_SPACE)
-        self.duty = duty
-        self.arr = array('H', 0 for _ in range(asize))
-        self._tim = Timer(5)
+        self._ch.pulse_width_percent(_SPACE)  # Turn off IR LED
+        self._duty = duty
+        self._tim = Timer(5)  # Timer 5 controls carrier on/off times
         self._tcb = self._cb
         self._tcb = self._cb
-        self.pretrans()
+        self.verbose = verbose
+        self.arr = array('H', 0 for _ in range(asize))  # on/off times (μs)
+        self.carrier = False  # Notional carrier state while encoding biphase
+        self.aptr = 0  # Index into array
 
     # Before populating array, zero pointer, set notional carrier state (off).
 
     # Before populating array, zero pointer, set notional carrier state (off).
-    def pretrans(self):
-        self.aptr = 0  # Index into array
+    def transmit(self, addr, data, toggle=0):  # NEC: toggle is unused
+        self.aptr = 0  # Inital conditions for tx: index into array
         self.carrier = False
         self.carrier = False
+        self.tx(addr, data, toggle)
+        self.append(_STOP)
+        self.aptr = 0  # Reset pointer
+        self._cb(self._tim)  # Initiate physical transmission.
 
 
-    def start(self):
-        self.aptr = 0  # Reset pointer and initiate TX.
-        self._cb(self._tim)
-
-    def _cb(self, t):
+    def _cb(self, t):  # T5 callback, generate a carrier mark or space
         t.deinit()
         p = self.aptr
         v = self.arr[p]
         if v == _STOP:
             self._ch.pulse_width_percent(_SPACE)  # Turn off IR LED.
             return
         t.deinit()
         p = self.aptr
         v = self.arr[p]
         if v == _STOP:
             self._ch.pulse_width_percent(_SPACE)  # Turn off IR LED.
             return
-        self._ch.pulse_width_percent(_SPACE if p & 1 else self.duty)
+        self._ch.pulse_width_percent(_SPACE if p & 1 else self._duty)
         self._tim.init(prescaler=84, period=v, callback=self._tcb)
         self.aptr += 1
 
         self._tim.init(prescaler=84, period=v, callback=self._tcb)
         self.aptr += 1
 
@@ -67,23 +69,22 @@ class IR:
             self.arr[self.aptr] = t
             self.aptr += 1
             self.carrier = not self.carrier  # Keep track of carrier state
             self.arr[self.aptr] = t
             self.aptr += 1
             self.carrier = not self.carrier  # Keep track of carrier state
-            print('append', t, 'carrier', self.carrier)
+            self.verbose and print('append', t, 'carrier', self.carrier)
 
     def add(self, t):  # Increase last time value
 
     def add(self, t):  # Increase last time value
-        print('add', t)
+        self.verbose and print('add', t)
         self.arr[self.aptr - 1] += t  # Carrier unaffected
 
 # NEC protocol
 class NEC(IR):
 
         self.arr[self.aptr - 1] += t  # Carrier unaffected
 
 # NEC protocol
 class NEC(IR):
 
-    def __init__(self, pin, freq=38000):  # NEC specifies 38KHz
-        super().__init__(pin, freq, 68, 50)
+    def __init__(self, pin, freq=38000, verbose=False):  # NEC specifies 38KHz
+        super().__init__(pin, freq, 68, 50, verbose)
 
     def _bit(self, b):
         self.append(_TBURST, _T_ONE if b else _TBURST)
 
 
     def _bit(self, b):
         self.append(_TBURST, _T_ONE if b else _TBURST)
 
-    def transmit(self, addr, data, _=0):  # Ignore toggle if passed
-        self.pretrans()  # Set initial conditions
+    def tx(self, addr, data, _):  # Ignore toggle
         self.append(9000, 4500)
         if addr < 256:  # Short address: append complement
             addr |= ((addr ^ 0xff) << 8)
         self.append(9000, 4500)
         if addr < 256:  # Short address: append complement
             addr |= ((addr ^ 0xff) << 8)
@@ -94,24 +95,22 @@ class NEC(IR):
         for x in range(16):
             self._bit(data & 1)
             data >>= 1
         for x in range(16):
             self._bit(data & 1)
             data >>= 1
-        self.append(_TBURST, _STOP)
-        self.start()
+        self.append(_TBURST,)
 
     def repeat(self):
         self.aptr = 0
 
     def repeat(self):
         self.aptr = 0
-        self.append(9000, 2250, _TBURST, _STOP)
+        self.append(9000, 2250, _TBURST)
 
 
 # Philips RC5 protocol
 class RC5(IR):
 
 
 
 # Philips RC5 protocol
 class RC5(IR):
 
-    def __init__(self, pin, freq=36000):
-        super().__init__(pin, freq, 28, 30)
+    def __init__(self, pin, freq=36000, verbose=False):
+        super().__init__(pin, freq, 28, 30, verbose)
 
 
-    def transmit(self, addr, data, toggle):
-        self.pretrans()  # Set initial conditions
+    def tx(self, addr, data, toggle):
         d = (data & 0x3f) | ((addr & 0x1f) << 6) | ((data & 0x40) << 6) | ((toggle & 1) << 11)
         d = (data & 0x3f) | ((addr & 0x1f) << 6) | ((data & 0x40) << 6) | ((toggle & 1) << 11)
-        print(bin(d))
+        self.verbose and print(bin(d))
         mask = 0x2000
         while mask:
             if mask == 0x2000:
         mask = 0x2000
         while mask:
             if mask == 0x2000:
@@ -124,17 +123,14 @@ class RC5(IR):
                 else:
                     self.append(_T_RC5, _T_RC5)
             mask >>= 1
                 else:
                     self.append(_T_RC5, _T_RC5)
             mask >>= 1
-        self.append(_STOP)
-        self.start()
 
 # Philips RC6 mode 0 protocol
 class RC6_M0(IR):
 
 
 # Philips RC6 mode 0 protocol
 class RC6_M0(IR):
 
-    def __init__(self, pin, freq=36000):
-        super().__init__(pin, freq, 44, 30)
+    def __init__(self, pin, freq=36000, verbose=False):
+        super().__init__(pin, freq, 44, 30, verbose)
 
 
-    def transmit(self, addr, data, toggle):
-        self.pretrans()  # Set initial conditions
+    def tx(self, addr, data, toggle):
         # leader, 1, 0, 0, 0
         self.append(2666, _T2_RC6, _T_RC6, _T2_RC6, _T_RC6, _T_RC6, _T_RC6, _T_RC6, _T_RC6)
         # Append a single bit of twice duration
         # leader, 1, 0, 0, 0
         self.append(2666, _T2_RC6, _T_RC6, _T2_RC6, _T_RC6, _T_RC6, _T_RC6, _T_RC6, _T_RC6)
         # Append a single bit of twice duration
@@ -145,7 +141,7 @@ class RC6_M0(IR):
             self.append(_T2_RC6, _T2_RC6)
         d = (data & 0xff) | ((addr & 0xff) << 8)
         mask = 0x8000
             self.append(_T2_RC6, _T2_RC6)
         d = (data & 0xff) | ((addr & 0xff) << 8)
         mask = 0x8000
-        print('toggle', toggle, self.carrier, bool(d & mask))
+        self.verbose and print('toggle', toggle, self.carrier, bool(d & mask))
         while mask:
             bit = bool(d & mask)
             if bit ^ self.carrier:
         while mask:
             bit = bool(d & mask)
             if bit ^ self.carrier:
@@ -154,5 +150,3 @@ class RC6_M0(IR):
                 self.add(_T_RC6)
                 self.append(_T_RC6)
             mask >>= 1
                 self.add(_T_RC6)
                 self.append(_T_RC6)
             mask >>= 1
-        self.append(_STOP)
-        self.start()
index 2d787285315fb1ee032d343882e8e3c62f32753c..0220c7b894f4aa6618ee802f5d7dd8e05976d44b 100644 (file)
@@ -54,13 +54,13 @@ async def main(proto):
         # Option to send REPEAT code. Most remotes do this.
         rep_code = True
     elif proto == 5:
         # Option to send REPEAT code. Most remotes do this.
         rep_code = True
     elif proto == 5:
-        irb = RC5(pin, 38000)
+        irb = RC5(pin, 38000)  # My decoder chip is 38KHz
     elif proto == 6:
     elif proto == 6:
-        irb = RC6_M0(pin, 38000)
+        irb = RC6_M0(pin, 38000, True)  # Verbose
 
     b = []  # Rbutton instances
     b.append(Rbutton(irb, Pin('X3', Pin.IN, Pin.PULL_UP), 0x1, 0x7, rep_code))
 
     b = []  # Rbutton instances
     b.append(Rbutton(irb, Pin('X3', Pin.IN, Pin.PULL_UP), 0x1, 0x7, rep_code))
-    b.append(Rbutton(irb, Pin('X4', Pin.IN, Pin.PULL_UP), 0x10, 0xb, rep_code))
+    b.append(Rbutton(irb, Pin('X4', Pin.IN, Pin.PULL_UP), 0xfa, 0xb, rep_code))
     led = LED(1)
     while True:
         await asyncio.sleep_ms(500)  # Obligatory flashing LED.
     led = LED(1)
     while True:
         await asyncio.sleep_ms(500)  # Obligatory flashing LED.