-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathir.py
More file actions
178 lines (164 loc) · 5 KB
/
Copy pathir.py
File metadata and controls
178 lines (164 loc) · 5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
'''IR decoder
Marc Hoffman 2017
Wiring any available GPIO input pin can be used, Timeline is tight with Python isr.
'''
from machine import Pin,Timer,disable_irq,enable_irq
import time,array,math
import micropython
from time import ticks_us, ticks_diff
micropython.alloc_emergency_exception_buf(100)
class DummyPort:
def high(self):
pass
def low(self):
pass
class irrecv:
'''irrecv receive IR signal on pin into circular buffer'''
def __init__(self,pno=4,bsz=1024,dbgport=None):
self.BUFSZ=int(pow(2, math.ceil(math.log(bsz)/math.log(2))))
self.MASK=self.BUFSZ-1
self.pin=pno
self.ir=Pin(pno,Pin.IN)
self.buf=array.array('i',0 for i in range(self.BUFSZ))
self.ledge=0
self.wptr=0
self.rptr=0
self.dbgport=dbgport
if dbgport is None:
self.dbgport=DummyPort()
self.dbgport.low()
# cache ticks functions for native call
self.ticks_diff = time.ticks_diff
self.ticks_us = time.ticks_us
self.start()
def __repr__(self):
return "<irrecv: {}, wptr={} rptr={}>".format(self.pin,
self.wptr,self.rptr)
@micropython.native
def timeseq_isr(self,p):
'''compute edge to edge transition time, ignore polarity'''
e=self.ticks_us()
self.dbgport.high()
s=2*p.value()-1
d=self.ticks_diff(e,self.ledge)
self.ledge=e
self.buf[self.wptr]=d*s
self.wptr=(self.wptr+1)&self.MASK
self.dbgport.low()
def stop(self):
'''disable isr'''
self.ir.deinit()
def start(self):
self.ir.irq(trigger=Pin.IRQ_FALLING|Pin.IRQ_RISING,handler=self.timeseq_isr)
def reset(self):
state=disable_irq()
self.wptr=0
self.rptr=0
enable_irq(state)
def read(self):
w=self.wptr
r=self.rptr
n=w-r
if n>=0:
x=self.buf[r:w]
elif n<0:
x=self.buf[r:]+self.buf[:w]
self.rptr=w
return x
class DecodeError(Exception):
pass
class decoder:
'''ir decoder base class'''
def __init__(self,eps=64):
self.eps=eps
def match(self,measured,setpt,debug=False):
d=abs(measured-setpt)
ceil=((setpt*0x2F00)>>15) # ~25%
if debug:
print("measured={} delta={} ceil={} setp={}".format(measured,d,ceil,setpt))
return d<ceil
def scan(self,timeseq,code,debug=False):
n=len(timeseq)
i=0
while i<n and not self.match(timeseq[i],code,debug=debug):
i+=1
if i<n:
return timeseq[i:]
else:
return None
class nec(decoder):
'''nec decoder
geometry follows in terms of us valid sequneces start with
9000us MARK 4500us SPACE [BIT_MARK SPACE]*32
'''
HDR_MARK = 9000
HDR_SPACE = 4500
BIT_MARK = 560
ONE_SPACE = 1690
ZERO_SPACE = 560
RPT_SPACE = 2250
BITS = 32
def __init__(self):
super().__init__()
def match(self,v,code,debug=False):
return super().match(abs(v),code,debug=debug)
def __call__(self,inp,debug=False):
timeseq=self.scan(inp,self.HDR_MARK)
if timeseq is None:
return None
n=len(timeseq)
if debug:
print(timeseq[:4])
if (n>2
and self.match(timeseq[1],self.RPT_SPACE,debug=debug)
and self.match(timeseq[2],self.ZERO_SPACE,debug=debug)):
return ('repeat',0,timeseq[3:])
if (n>1 and not self.match(timeseq[1],self.HDR_SPACE,debug=debug)):
return None
if n<2*self.BITS+2:
return None
data=0
samps=[]
for i in range(self.BITS):
if not self.match(timeseq[2+2*i],self.BIT_MARK,debug=debug):
raise DecodeError
if self.match(timeseq[2+2*i+1],self.ONE_SPACE,debug=debug):
b=1
elif self.match(timeseq[2+2*i+1],self.ZERO_SPACE,debug=debug):
b=0
else:
raise DecodeError
data=(data<<1)|b
samps.append(b)
rest=timeseq[2+self.BITS*2:]
return (data,samps,rest)
class IRnec(nec):
def __init__(self,ir):
self.ir=ir
self.samples=array.array('i')
def __call__(self,debug=False):
self.samples=self.samples+self.ir.read()
if len(self.samples):
x=super().__call__(self.samples,debug=debug)
if x is None:
return None
(data,samps,rest)=x
self.samples=rest
if isinstance(data,int):
return hex(data)
return data
return None
def reset(self):
self.samples=array.array('i')
dbg=Pin(5,Pin.OUT)
n=IRnec(irrecv(4,bsz=256,dbgport=dbg))
def test():
while True:
try:
x=n()
except DecodeError:
print('DecodeError')
print(n.samples)
return
if x:
print(x)