70 lines
2.1 KiB
Python
70 lines
2.1 KiB
Python
# ir_rx __init__.py Decoder for IR remote control using synchronous code
|
|
# IR_RX abstract base class for IR receivers.
|
|
|
|
# Author: Peter Hinch
|
|
# Copyright Peter Hinch 2020-2021 Released under the MIT license
|
|
|
|
from machine import Timer, Pin
|
|
from array import array
|
|
from utime import ticks_us
|
|
|
|
# Save RAM
|
|
# from micropython import alloc_emergency_exception_buf
|
|
# alloc_emergency_exception_buf(100)
|
|
|
|
# On 1st edge start a block timer. While the timer is running, record the time
|
|
# of each edge. When the timer times out decode the data. Duration must exceed
|
|
# the worst case block transmission time, but be less than the interval between
|
|
# a block start and a repeat code start (~108ms depending on protocol)
|
|
|
|
class IR_RX():
|
|
# Result/error codes
|
|
# Repeat button code
|
|
REPEAT = -1
|
|
# Error codes
|
|
BADSTART = -2
|
|
BADBLOCK = -3
|
|
BADREP = -4
|
|
OVERRUN = -5
|
|
BADDATA = -6
|
|
BADADDR = -7
|
|
|
|
def __init__(self, pin, nedges, tblock, callback, *args): # Optional args for callback
|
|
self._pin = pin
|
|
self._nedges = nedges
|
|
self._tblock = tblock
|
|
self.callback = callback
|
|
self.args = args
|
|
self._errf = lambda _ : None
|
|
self.verbose = False
|
|
|
|
self._times = array('i', (0 for _ in range(nedges + 1))) # +1 for overrun
|
|
pin.irq(handler = self._cb_pin, trigger = (Pin.IRQ_FALLING | Pin.IRQ_RISING))
|
|
self.edge = 0
|
|
self.tim = Timer(-1) # Sofware timer
|
|
self.cb = self.decode
|
|
|
|
# Pin interrupt. Save time of each edge for later decode.
|
|
def _cb_pin(self, line):
|
|
t = ticks_us()
|
|
# On overrun ignore pulses until software timer times out
|
|
if self.edge <= self._nedges: # Allow 1 extra pulse to record overrun
|
|
if not self.edge: # First edge received
|
|
self.tim.init(period=self._tblock , mode=Timer.ONE_SHOT, callback=self.cb)
|
|
self._times[self.edge] = t
|
|
self.edge += 1
|
|
|
|
def do_callback(self, cmd, addr, ext, thresh=0):
|
|
self.edge = 0
|
|
if cmd >= thresh:
|
|
self.callback(cmd, addr, ext, *self.args)
|
|
else:
|
|
self._errf(cmd)
|
|
|
|
def error_function(self, func):
|
|
self._errf = func
|
|
|
|
def close(self):
|
|
self._pin.irq(handler = None)
|
|
self.tim.deinit()
|