]> vault307.fbx.one Git - micorpython_ir.git/commitdiff
Support transmit and receive on Samsung remotes.
authorPeter Hinch <peter@hinch.me.uk>
Mon, 6 Jun 2022 17:04:55 +0000 (18:04 +0100)
committerPeter Hinch <peter@hinch.me.uk>
Mon, 6 Jun 2022 17:04:55 +0000 (18:04 +0100)
README.md
RECEIVER.md
TRANSMITTER.md
ir_rx/acquire.py
ir_rx/nec.py
ir_rx/samsung.py [deleted file]
ir_rx/test.py
ir_tx/nec.py

index 48259c5f25034e06ae3c675d27b87bae22be717c..f33feb50a585c309ab92d050ec27bb8f4889de6a 100644 (file)
--- a/README.md
+++ b/README.md
@@ -52,6 +52,7 @@ The drivers support NEC and Sony protocols plus two Philips protocols, namely
 RC-5 and RC-6 mode 0. There is also support for the OrtekMCE protocol used on
 VRC-1100 remotes. These originally supported Microsoft Media Center but can be
 used to control Kodi and (with a suitable receiver) to emulate a PC keyboard.
+The Samsung protocol (NEC variant) is also supported.
 
 Examining waveforms from various remote controls it is evident that numerous
 protocols exist. Some are doubtless proprietary and undocumented. The supported
@@ -77,14 +78,14 @@ microcontroller.
 In my testing a 38KHz demodulator worked with 36KHz and 40KHz remotes, but this
 is obviously neither guaranteed nor optimal.
 
-The transmitter requires a Pyboard 1.x (not Lite), a Pyboard D or an ESP32.
-Output is via an IR LED which will need a transistor to provide sufficient
-current. The ESP32 requires an extra transistor to work as a transmitter.
+The transmitter requires a Pyboard 1.x (not Lite), a Pyboard D, an ESP32 or
+Raspberry Pico (RP2). Output is via an IR LED which will need a transistor to
+provide sufficient current.
 
 ## 3.1 Carrier frequencies
 
-These are as follows. The Samsung and Panasonic remotes appear to use
-proprietary protocols and are not supported by these drivers.
+These are as follows. The Panasonic remote appears to use a proprietary
+protocol and is not supported by these drivers.
 
 | Protocol  | F KHz | How found     | Support |
 |:---------:|:-----:|:-------------:|:-------:|
@@ -92,7 +93,7 @@ proprietary protocols and are not supported by these drivers.
 | RC-5 RC-6 | 36    | Spec/measured | Y       |
 | Sony      | 40    | Spec/measured | Y       |
 | MCE       | 38    | Measured      | Y       | 
-| Samsung   | 38    | Measured      | N       |
+| Samsung   | 38    | Measured      | Y       |
 | Panasonic | 36.3  | Measured      | N       |
 
 # 4. Receiver limitations
@@ -111,9 +112,14 @@ excellent resource.
 
 The NEC protocol:  
 [altium](http://techdocs.altium.com/display/FPGA/NEC+Infrared+Transmission+Protocol)  
-[circuitvalley](http://www.circuitvalley.com/2013/09/nec-protocol-ir-infrared-remote-control.html)
+[circuitvalley](http://www.circuitvalley.com/2013/09/nec-protocol-ir-infrared-remote-control.html)  
 [sbprojects.net](https://www.sbprojects.net/knowledge/ir/nec.php)
 
+The Samsung protocol:  
+[Rustic Engineering](https://rusticengineering.wordpress.com/2011/02/09/infrared-room-control-with-samsung-ir-protocol/)  
+[TechDesign Electronics](https://www.techdesign.be/projects/011/011_waves.htm) Waveforms of various protocols.  
+
+
 Philips protocols:  
 [RC5 Wikipedia](https://en.wikipedia.org/wiki/RC-5)  
 [RC5 sbprojects.net](https://www.sbprojects.net/knowledge/ir/rc5.php)  
index fe1493efbcd4d02e3418e0aa1a21a8c9dd498440..13ce77a24339cb1557c1e9aa5c011fe953fe7bd4 100644 (file)
@@ -141,9 +141,9 @@ Class variables:
  1. These are constants defining the NEC repeat code and the error codes sent
  to the error function. They are discussed in [section 4](./RECEIVER.md#4-errors).
 
-#### NEC classes
+#### NEC classes (includes Samsung)
 
-`NEC_8`, `NEC_16`
+`NEC_8`, `NEC_16`, `SAMSUNG`
 
 Typical invocation:
 ```python
@@ -157,6 +157,13 @@ The `NEC_8` class enables error checking for remotes that return an 8 bit
 address: the complement is checked and the address returned as an 8-bit value.
 A 16-bit address will result in an error.
 
+The `SAMSUNG` class returns 16 bit address and data values. The remote sample
+tested did not issue repeat codes - if a button is held down it simply repeated
+the original value. In common with other NEC classes the callback receives a
+value of 0 in the `ctrl` arg.
+
+Thanks are due to J.E.Tannenbaum for information about the Samsung protocol.
+
 #### Sony classes
 
 `SONY_12`, `SONY_15`, `SONY_20`
index a328d68f4fcaf7c5354415aee405a84b38f1600c..c76995bb5390014de2e4b4dcbd55519aa818ab0c 100644 (file)
@@ -22,7 +22,10 @@ device similar to the ESP32 RMT. The device driver is
 [documented here](./RP2_RMT.md); this is for experimenters and those wanting to
 use the library in conjunction with their own PIO assembler code.
 
-## 1.1 Pyboard Wiring
+## 1.1 Wiring
+
+All microcontrollers require an external circuit to drive the LED. The notes
+below on specific microcontrollers assume that such a circuit is used.
 
 I use the following circuit which delivers just under 40mA to the diode. R2 may
 be reduced for higher current.  
@@ -169,7 +172,7 @@ skipping validation.
 | RC6_M0   | 6.0ms | 2.0ms   |
 | MCE      | 6.7ms | 2.0ms   |
 
-#### NEC class
+#### NEC class (also Samsung)
 
 Class `NEC`. Example invocation:
 ```python
@@ -187,6 +190,16 @@ the complement for values < 256.
 
 A value passed in `toggle` is ignored.
 
+For Samsung protocol set the `samsung` class variable `True`:
+```python
+from ir_tx.nec import NEC
+NEC.samsung=True
+```
+Samsung remotes do not seem to use repeat codes: the sample I have simply
+repeats the original code.
+
+Thanks are due to J.E.Tannenbaum for information about the Samsung protocol.
+
 #### Sony classes
 
 Classes `SONY_12`, `SONY_15` and `SONY_20`. Example invocation:
index ea0b2e4eafd35499fa3c7ca2d86dcec57739762c..af3ab38ba17ad61a46c58ff4700ef3a0c6f9fa5b 100644 (file)
@@ -70,8 +70,8 @@ class IR_GET(IR_RX):
                     print('Protocol start {} {} Burst length {} duration {}'.format(burst[0], burst[1], lb, duration))
                     ok = True
 
-            if not ok and near(burst[0], 4500) and near(burst[1], 4500):  # Samsung?
-                print('Unsupported protocol. Samsung?')
+            if not ok and near(burst[0], 4500) and near(burst[1], 4500) and lb == 67:  # Samsung
+                print('Samsung')
                 ok = True
 
             if not ok and near(burst[0], 3500) and near(burst[1], 1680):  # Panasonic?
index e516924412c8a9bf009e427f3062b80ff97f56b6..011b13dda9af7cd816bb97e60de97525534c5ebe 100644 (file)
@@ -1,26 +1,29 @@
 # nec.py Decoder for IR remote control using synchronous code
-# Supports NEC protocol.
+# Supports NEC and Samsung protocols.
+# With thanks to J.E. Tannenbaum for information re Samsung protocol
+
 # For a remote using NEC see https://www.adafruit.com/products/389
 
 # Author: Peter Hinch
-# Copyright Peter Hinch 2020 Released under the MIT license
+# Copyright Peter Hinch 2020-2022 Released under the MIT license
 
 from utime import ticks_us, ticks_diff
 from ir_rx import IR_RX
 
 class NEC_ABC(IR_RX):
-    def __init__(self, pin, extended, callback, *args):
+    def __init__(self, pin, extended, samsung, callback, *args):
         # Block lasts <= 80ms (extended mode) and has 68 edges
         super().__init__(pin, 68, 80, callback, *args)
         self._extended = extended
         self._addr = 0
+        self._leader = 2500 if samsung else 4000  # 4.5ms for Samsung else 9ms
 
     def decode(self, _):
         try:
             if self.edge > 68:
                 raise RuntimeError(self.OVERRUN)
             width = ticks_diff(self._times[1], self._times[0])
-            if width < 4000:  # 9ms leading mark for all valid data
+            if width < self._leader:  # 9ms leading mark for all valid data
                 raise RuntimeError(self.BADSTART)
             width = ticks_diff(self._times[2], self._times[1])
             if width > 3000:  # 4.5ms space for normal data
@@ -55,8 +58,12 @@ class NEC_ABC(IR_RX):
 
 class NEC_8(NEC_ABC):
     def __init__(self, pin, callback, *args):
-        super().__init__(pin, False, callback, *args)
+        super().__init__(pin, False, False, callback, *args)
 
 class NEC_16(NEC_ABC):
     def __init__(self, pin, callback, *args):
-        super().__init__(pin, True, callback, *args)
+        super().__init__(pin, True, False, callback, *args)
+
+class SAMSUNG(NEC_ABC):
+    def __init__(self, pin, callback, *args):
+        super().__init__(pin, True, True, callback, *args)
diff --git a/ir_rx/samsung.py b/ir_rx/samsung.py
deleted file mode 100644 (file)
index 382dcbf..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-# samsung.py Decoder for IR remote control using synchronous code\r
-# Supports Samsung TV remote protocols.\r
-\r
-# Author: J.E. Tannenbaum\r
-# Copyright J.E.Tannenbaum 2021 Released under the MIT license\r
-\r
-from utime import ticks_us, ticks_diff\r
-from ir_rx import IR_RX\r
-\r
-class SAMSUNG(IR_RX):\r
-    def __init__(self, pin, callback, *args):\r
-        super().__init__(pin, 68, 80, callback, *args)\r
-\r
-    def decode(self, _):\r
-        def near(v, target):\r
-            return target * 0.8 < v < target * 1.2\r
-\r
-        lb = self.edge - 1  # Possible length of burst\r
-        burst = []\r
-        for x in range(lb):\r
-            dt = ticks_diff(self._times[x + 1], self._times[x])\r
-            if x > 0 and dt > 10000:  # Reached gap between repeats\r
-                break\r
-            burst.append(dt)\r
-\r
-        lb = len(burst)  # Actual length\r
-        cmd = 0\r
-        if near(burst[0], 4500) and near(burst[1], 4500) and lb == 67:\r
-            # Skip the starting bits and the checksum at the end of the sequence\r
-            for x in range(2, lb - 1, 2):\r
-                cmd *= 2\r
-                # Test for logical 1 (One byte low, next byte high)\r
-                if burst[x] < 1000 and burst[x + 1] > 1000:\r
-                    cmd += 1\r
-\r
-        # Set up for new data burst and run user callback\r
-        self.do_callback(cmd, 0, 0)\r
index 48f342e2f4633a1ef70a6cde8fe815fb4dcca4c2..c4dbd7f4e39008818140658214b63d36eb647579 100644 (file)
@@ -2,7 +2,7 @@
 # Supports Pyboard, ESP32 and ESP8266
 
 # Author: Peter Hinch
-# Copyright Peter Hinch 2020 Released under the MIT license
+# Copyright Peter Hinch 2020-2022 Released under the MIT license
 
 # Run this to characterise a remote.
 
@@ -11,46 +11,49 @@ import time
 import gc
 from machine import Pin, freq
 from ir_rx.print_error import print_error  # Optional print of error codes
+
 # Import all implemented classes
-from ir_rx.nec import NEC_8, NEC_16
+from ir_rx.nec import NEC_8, NEC_16, SAMSUNG
 from ir_rx.sony import SONY_12, SONY_15, SONY_20
 from ir_rx.philips import RC5_IR, RC6_M0
 from ir_rx.mce import MCE
 
 # Define pin according to platform
-if platform == 'pyboard':
-    p = Pin('X3', Pin.IN)
-elif platform == 'esp8266':
+if platform == "pyboard":
+    p = Pin("X3", Pin.IN)
+elif platform == "esp8266":
     freq(160000000)
     p = Pin(13, Pin.IN)
-elif platform == 'esp32' or platform == 'esp32_LoBo':
+elif platform == "esp32" or platform == "esp32_LoBo":
     p = Pin(23, Pin.IN)
-elif platform == 'rp2':
+elif platform == "rp2":
     p = Pin(16, Pin.IN)
 
 # User callback
 def cb(data, addr, ctrl):
     if data < 0:  # NEC protocol sends repeat codes.
-        print('Repeat code.')
+        print("Repeat code.")
     else:
-        print('Data {:02x} Addr {:04x} Ctrl {:02x}'.format(data, addr, ctrl))
+        print(f"Data 0x{data:02x} Addr 0x{addr:04x} Ctrl 0x{ctrl:02x}")
+
 
 def test(proto=0):
-    classes = (NEC_8, NEC_16, SONY_12, SONY_15, SONY_20, RC5_IR, RC6_M0, MCE)
+    classes = (NEC_8, NEC_16, SONY_12, SONY_15, SONY_20, RC5_IR, RC6_M0, MCE, SAMSUNG)
     ir = classes[proto](p, cb)  # Instantiate receiver
     ir.error_function(print_error)  # Show debug information
-    #ir.verbose = True
+    # ir.verbose = True
     # A real application would do something here...
     try:
         while True:
-            print('running')
+            print("running")
             time.sleep(5)
             gc.collect()
     except KeyboardInterrupt:
         ir.close()
 
+
 # **** DISPLAY GREETING ****
-s = '''Test for IR receiver. Run:
+s = """Test for IR receiver. Run:
 from ir_rx.test import test
 test() for NEC 8 bit protocol,
 test(1) for NEC 16 bit,
@@ -60,7 +63,8 @@ test(4) for Sony SIRC 20 bit,
 test(5) for Philips RC-5 protocol,
 test(6) for RC6 mode 0.
 test(7) for Microsoft Vista MCE.
+test(8) for Samsung.
 
-Hit ctrl-c to stop, then ctrl-d to soft reset.'''
+Hit ctrl-c to stop, then ctrl-d to soft reset."""
 
 print(s)
index da1af24a8ae75a0f32735a04aedf56c7c5e61b4c..807ec68abb220eeead32a1d98cf0b638000308b7 100644 (file)
@@ -2,8 +2,9 @@
 # NEC protocol.
 
 # Author: Peter Hinch
-# Copyright Peter Hinch 2020 Released under the MIT license
+# Copyright Peter Hinch 2020-2022 Released under the MIT license
 
+# With thanks to J.E. Tannenbaum for information re Samsung protocol
 from micropython import const
 from ir_tx import IR, STOP
 
@@ -12,15 +13,19 @@ _T_ONE = const(1687)
 
 class NEC(IR):
     valid = (0xffff, 0xff, 0)  # Max addr, data, toggle
+    samsung = False
 
-    def __init__(self, pin, freq=38000, verbose=False):  # NEC specifies 38KHz
+    def __init__(self, pin, freq=38000, verbose=False):  # NEC specifies 38KHz also Samsung
         super().__init__(pin, freq, 68, 33, verbose)  # Measured duty ratio 33%
 
     def _bit(self, b):
         self.append(_TBURST, _T_ONE if b else _TBURST)
 
     def tx(self, addr, data, _):  # Ignore toggle
-        self.append(9000, 4500)
+        if self.samsung:
+            self.append(4500, 4500)
+        else:
+            self.append(9000, 4500)
         if addr < 256:  # Short address: append complement
             addr |= ((addr ^ 0xff) << 8)
         for _ in range(16):