Пример #1
0
class LED_Flashable():
    def __init__(self, loop, led_no):
        self.led = pyb.LED(led_no)
        self.event = Event()
        loop.create_task(self.flash_task())

    def flash(self, period_ms):
        if self.event.is_set():
            return
        self.event.set(period_ms)

    async def flash_task(self):
        while True:
            await self.event
            period_ms = self.event.value()
            self.event.clear()
            self.led.on()
            await asyncio.sleep_ms(period_ms)
            self.led.off()
Пример #2
0
class NEC_IR():
    def __init__(self, pin, callback, extended,
                 *args):  # Optional args for callback
        self._ev_start = Event()
        self._callback = callback
        self._extended = extended
        self._addr = 0
        self.block_time = 80 if extended else 73  # Allow for some tx tolerance (?)
        self._args = args
        self._times = array('i',
                            (0
                             for _ in range(_EDGECOUNT + 1)))  # +1 for overrun
        if platform == 'pyboard':
            ExtInt(pin, ExtInt.IRQ_RISING_FALLING, Pin.PULL_NONE, self._cb_pin)
        else:  # PR5962 ESP8266 hard IRQ's not supported
            pin.irq(handler=self._cb_pin,
                    trigger=(Pin.IRQ_FALLING | Pin.IRQ_RISING))
        #elif ESP32:
        #pin.irq(handler = self._cb_pin, trigger = (Pin.IRQ_FALLING | Pin.IRQ_RISING))
        #else:
        #pin.irq(handler = self._cb_pin, trigger = (Pin.IRQ_FALLING | Pin.IRQ_RISING), hard = True)
        self._edge = 0
        self._ev_start.clear()
        loop = asyncio.get_event_loop()
        loop.create_task(self._run())

    async def _run(self):
        loop = asyncio.get_event_loop()
        while True:
            await self._ev_start  # Wait until data collection has started
            # Compensate for asyncio latency
            latency = ticks_diff(loop.time(), self._ev_start.value())
            await asyncio.sleep_ms(self.block_time - latency
                                   )  # Data block should have ended
            self._decode()  # decode, clear event, prepare for new rx, call cb

    # 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 <= _EDGECOUNT:  # Allow 1 extra pulse to record overrun
            if not self._ev_start.is_set():  # First edge received
                loop = asyncio.get_event_loop()
                self._ev_start.set(loop.time())  # asyncio latency compensation
            self._times[self._edge] = t
            self._edge += 1

    def _decode(self):
        overrun = self._edge > _EDGECOUNT
        val = OVERRUN if overrun else BADSTART
        if not overrun:
            width = ticks_diff(self._times[1], self._times[0])
            if width > 4000:  # 9ms leading mark for all valid data
                width = ticks_diff(self._times[2], self._times[1])
                if width > 3000:  # 4.5ms space for normal data
                    if self._edge < _EDGECOUNT:
                        # Haven't received the correct number of edges
                        val = BADBLOCK
                    else:
                        # Time spaces only (marks are always 562.5µs)
                        # Space is 1.6875ms (1) or 562.5µs (0)
                        # Skip last bit which is always 1
                        val = 0
                        for edge in range(3, _EDGECOUNT - 2, 2):
                            val >>= 1
                            if ticks_diff(self._times[edge + 1],
                                          self._times[edge]) > 1120:
                                val |= 0x80000000
                elif width > 1700:  # 2.5ms space for a repeat code. Should have exactly 4 edges.
                    val = REPEAT if self._edge == 4 else BADREP
        addr = 0
        if val >= 0:  # validate. Byte layout of val ~cmd cmd ~addr addr
            addr = val & 0xff
            cmd = (val >> 16) & 0xff
            if addr == ((val >> 8) ^ 0xff) & 0xff:  # 8 bit address OK
                val = cmd if cmd == (val >> 24) ^ 0xff else BADDATA
                self._addr = addr
            else:
                addr |= val & 0xff00  # pass assumed 16 bit address to callback
                if self._extended:
                    val = cmd if cmd == (val >> 24) ^ 0xff else BADDATA
                    self._addr = addr
                else:
                    val = BADADDR
        if val == REPEAT:
            addr = self._addr  # Last valid addresss
        self._edge = 0  # Set up for new data burst and run user callback
        self._ev_start.clear()
        self._callback(val, addr, *self._args)
Пример #3
0
class NEC_IR():
    edgecount = 68
    block_time = 73 # 68.1ms nominal. Allow for some tx tolerance (?)
    def __init__(self, pin, callback):
        self._ev_start = Event()
        self._callback = callback
        self._times = array('i',  (0 for _ in range(self.edgecount + 1))) # 1 for overrun
        ExtInt(pin, ExtInt.IRQ_RISING_FALLING, Pin.PULL_NONE, self._cb_pin)
        self._reset()
        loop = asyncio.get_event_loop()
        loop.create_task(self._run())

    def _reset(self):
        self._edge = 0
        self._in_block = False
        self._overrun = False
        self._ev_start.clear()

    async def _run(self):
        loop = asyncio.get_event_loop()
        block_time = self.block_time
        while True:
            await self._ev_start  # Wait unitl data collection has started
            delta = block_time - ticks_diff(loop.time(), self._ev_start.value())
            await asyncio.sleep_ms(delta)  # Data block should have ended
            self._decode() # decode, clear event, prepare for new rx, call cb

    # Pin interrupt. Save time of each edge for later decode.
    def _cb_pin(self, line):
        if self._overrun: # Ignore pulses until software timer times out
            return
        if not self._in_block: # First edge received
            loop = asyncio.get_event_loop()
            self._ev_start.set(loop.time()) # time for latency compensation
            self._in_block = True
        self._times[self._edge] = ticks_us()
        if self._edge < self.edgecount:
            self._edge += 1
        else:
            self._overrun = True # Overrun. decode() will test and reset

    def _decode(self):
        val = -3 if self._overrun else 0
        if not self._overrun:
            width = ticks_diff(self._times[1], self._times[0])
            if width > 4000:  # 9ms leading mark for all valid data
                width = ticks_diff(self._times[2], self._times[1])
                if width > 3000: # 4.5ms space for normal data
                    if self._edge < self.edgecount:
                        val = -1  # Haven't received the correct number of edges
                    else: # Time spaces only (marks are identical)
                        for edge_no in range(3, self.edgecount, 2):
                            val &= 0x1fffffff # Constrain to 32 bit integer (b30 == b31)
                            val <<= 1 # nos. will still be unique because of logical inverse address
                            width = ticks_diff(self._times[edge_no + 1], self._times[edge_no])
                            if width > 1120:
                                val += 1
                elif width > 1700: # 2.5ms space for a repeat code. Should have exactly 4 edges.
                    val = 1 if self._edge == 4 else -2
        self._reset()
        self._callback(val)