_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:
- 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.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.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).
- 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.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
- 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.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
- print('add', t)
+ self.verbose and print('add', t)
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 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)
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
- self.append(9000, 2250, _TBURST, _STOP)
+ self.append(9000, 2250, _TBURST)
# 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)
- print(bin(d))
+ self.verbose and print(bin(d))
mask = 0x2000
while mask:
if mask == 0x2000:
else:
self.append(_T_RC5, _T_RC5)
mask >>= 1
- self.append(_STOP)
- self.start()
# 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
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:
self.add(_T_RC6)
self.append(_T_RC6)
mask >>= 1
- self.append(_STOP)
- self.start()