]>
vault307.fbx.one Git - micorpython_ir.git/blob - ir_tx/__init__.py
ef52e84a3cccc8126a56d8968dc7dd9aa68216ba
1 # __init__.py Nonblocking IR blaster
2 # Runs on Pyboard D or Pyboard 1.x (not Pyboard Lite) and ESP32
4 # Released under the MIT License (MIT). See LICENSE.
6 # Copyright (c) 2020 Peter Hinch
7 from sys
import platform
8 ESP32
= platform
== 'esp32' or platform
== 'esp32_LoBo'
10 from machine
import Pin
, Timer
, PWM
, freq
12 from pyb
import Pin
, Timer
# Pyboard does not support machine.PWM
14 from micropython
import const
15 from array
import array
18 # micropython.alloc_emergency_exception_buf(100)
22 # If the wiring is such that 3.3V turns the LED off, set _SPACE as follows
23 # On Pyboard 100, on ESP32 1023
25 STOP
= const(0) # End of data
27 # IR abstract base class. Array holds periods in μs between toggling 36/38KHz
28 # carrier on or off. Physical transmission occurs in an ISR context controlled
29 # by timer 2 and timer 5. See README.md for details of operation.
32 def __init__(self
, pin
, cfreq
, asize
, duty
, verbose
):
35 self
._pwm
= PWM(pin
) # Produces 36/38/40KHz carrier
37 self
._pwm
.init(freq
=cfreq
, duty
=_SPACE
)
38 # ESP32: 0 <= duty <= 1023
39 self
._duty
= round((duty
if not _SPACE
else (100 - duty
)) * 10.23)
40 self
._tim
= Timer(-1) # Controls carrier on/off times
41 self
._off
= self
.esp_off
# Turn IR LED off
42 self
._onoff
= self
.esp_onoff
# Set IR LED state and refresh timer
44 tim
= Timer(2, freq
=cfreq
) # Timer 2/pin produces 36/38/40KHz carrier
45 self
._ch
= tim
.channel(1, Timer
.PWM
, pin
=pin
)
46 self
._ch
.pulse_width_percent(_SPACE
) # Turn off IR LED
47 # Pyboard: 0 <= pulse_width_percent <= 100
48 self
._duty
= duty
if not _SPACE
else (100 - duty
)
49 self
._tim
= Timer(5) # Timer 5 controls carrier on/off times
50 self
._off
= self
.pb_off
51 self
._onoff
= self
.pb_onoff
52 self
._tcb
= self
.cb
# Pre-allocate
53 self
.verbose
= verbose
54 self
.arr
= array('H', 0 for _
in range(asize
)) # on/off times (μs)
55 self
.carrier
= False # Notional carrier state while encoding biphase
56 self
.aptr
= 0 # Index into array
58 # Before populating array, zero pointer, set notional carrier state (off).
59 def transmit(self
, addr
, data
, toggle
=0): # NEC: toggle is unused
60 self
.aptr
= 0 # Inital conditions for tx: index into array
62 self
.tx(addr
, data
, toggle
)
64 self
.aptr
= 0 # Reset pointer
65 self
.cb(self
._tim
) # Initiate physical transmission.
67 # Turn IR LED off (pyboard and ESP32 variants)
69 self
._ch
.pulse_width_percent(_SPACE
)
72 self
._pwm
.duty(_SPACE
)
74 # Turn IR LED on or off and re-initialise timer (pyboard and ESP32 variants)
76 def pb_onoff(self
, p
, v
):
77 self
._ch
.pulse_width_percent(_SPACE
if p
& 1 else self
._duty
)
78 self
._tim
.init(prescaler
=84, period
=v
, callback
=self
._tcb
)
81 def esp_onoff(self
, p
, v
):
82 self
._pwm
.duty(_SPACE
if p
& 1 else self
._duty
)
83 self
._tim
.init(mode
=Timer
.ONE_SHOT
, freq
=v
, callback
=self
.cb
)
85 def cb(self
, t
): # T5 callback, generate a carrier mark or space
90 self
._off
() # Turn off IR LED.
95 def append(self
, *times
): # Append one or more time peiods to .arr
98 t
-= 350 # ESP32 sluggishness
99 t
= round(1_000_000 / t
) # Store in Hz
100 self
.arr
[self
.aptr
] = t
102 self
.carrier
= not self
.carrier
# Keep track of carrier state
103 self
.verbose
and print('append', t
, 'carrier', self
.carrier
)
105 def add(self
, t
): # Increase last time value
107 self
.verbose
and print('add', t
)
108 # .carrier unaffected
111 self
.arr
[self
.aptr
- 1] = round((self
.arr
[self
.aptr
- 1] / 1_000_000 + t
) / 1_000_000)
113 self
.arr
[self
.aptr
- 1] += t