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
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 |
|:---------:|:-----:|:-------------:|:-------:|
| 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
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)
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
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`
[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.
| RC6_M0 | 6.0ms | 2.0ms |
| MCE | 6.7ms | 2.0ms |
-#### NEC class
+#### NEC class (also Samsung)
Class `NEC`. Example invocation:
```python
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:
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?
# 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
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)
+++ /dev/null
-# 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
# 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.
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,
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)
# 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
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):