示例#1
0
class ButtonTypedI2c(Button):
    '''
    I2C Button/Switch Array Class

    provide event checking ability to derived class,
    should not use directly by end-user.
    The checking events include:

      - Button.EV_SINGLE_CLICK
      - Button.EV_DOUBLE_CLICK
      - Button.EV_LONG_PRESS
      - Button.EV_LEVEL_CHANGED

    Args:
        address(int): optional, the I2C address of the connected device.
        evt_en(bool): optional, default True

            True:  provide event checking ability.

            False: used in poll environment, manually call :class:`ButtonTypedI2c.read`.
    '''
    def __init__(self, address=0x03, evt_en=True):
        super(ButtonTypedI2c, self).__init__(0)

        self.bus = Bus()
        self._addr = address

        # Initialise the I2C button device
        self.dev_id = 0
        self._probe_uid()
        self._version = 0
        self.version()
        self._size = self.size()

        self._set_mode(True)

        self.__last_evt = None
        self.__last_evt = self.read()

        self.key_names = _grove_5way_tactile_keys
        if self._size == 6:
            self.key_names = _grove_6pos_dip_switch_keys

        self.__thrd_exit = False
        self.__thrd = None
        if not evt_en:
            return

        if self.__thrd is None or not self.__thrd.is_alive():
            self.__thrd = threading.Thread( \
                    target = ButtonTypedI2c.__thrd_chk_evt, \
                    args = (self,))
            self.__thrd.setDaemon(True)
            self.__thrd.start()

    def __del__(self):
        if not self.__thrd:
            return

        self.__thrd_exit = True
        while self.__thrd.isAlive():
            time.sleep(_CYCLE_PERIOD / _CYCLE_UNIT)
        self.__thrd.join()

    # Thread to check events
    def __thrd_chk_evt(self):
        self.__last_time = time.time()
        while not self.__thrd_exit:
            # or self.__state != self.KEY_STATE_IDLE:
            t = time.time()
            dt, self.__last_time = t - self.__last_time, t

            evt = self.read()
            if not evt[0]:
                time.sleep(_CYCLE_PERIOD)
                continue

            for i in range(0, self.size()):
                if evt[i + 1] & ~self.EV_RAW_STATUS:
                    pressed = bool(evt[i + 1] & self.EV_RAW_STATUS)
                    self._index = i
                    self._send_event(evt[i + 1], pressed, t)
            time.sleep(_CYCLE_PERIOD)

    def _probe_uid(self):
        ID_LEN = 4
        for tr in range(4):
            v = self.bus.read_i2c_block_data(self._addr, _CMD_GET_DEV_ID,
                                             ID_LEN)
            # print("GET_DEV_ID = {}".format(v))
            did = 0
            for i in range(ID_LEN):
                did = (did >> 8) | (int(v[i]) << 24)
            # print("DEV_ID = {:8X}".format(did))
            if (did >> 16) == VID_MULTI_SWITCH:
                self.dev_id = did
                return self.dev_id
            self.bus.read_byte(self._addr, True)

    def version(self):
        '''
        Get the device firmware version.

        Returns:
            (int): firmware version, the first version is 1
        '''
        VER_LEN = 10
        if not self.dev_id:
            return 0
        v = self.bus.read_i2c_block_data(self._addr, _CMD_TEST_GET_VER,
                                         VER_LEN)
        # print("GET_VER = {}".format(str(v)))
        version = v[6] - ord('0')
        version = version * 10 + (v[8] - ord('0'))
        # print("version = {}".format(version))
        self._version = version
        return self._version

    def size(self):
        '''
        Get the button count the device have.

        Returns:
            (int): button count
        '''
        if (self.dev_id >> 16) != VID_MULTI_SWITCH:
            return 0
        if (self.dev_id & 0xFFFF) == PID_5_WAY_TACTILE_SWITCH:
            return 5
        if (self.dev_id & 0xFFFF) == PID_6_POS_DIP_SWITCH:
            return 6
        return 0

    def name(self, index=None):
        '''
        Get the device name or specified button name

        Args:
            index(int): optional, the index number of button to get name.
                        if not specified, return the device name.

        Returns:
            (string): the name of the device or pecified button
        '''
        if (self.dev_id >> 16) != VID_MULTI_SWITCH:
            return "Invalid dev"
        if not index is None:
            if index < 0 or index >= self._size:
                return "Invalid index"
            return self.key_names[index]

        if (self.dev_id & 0xFFFF) == PID_5_WAY_TACTILE_SWITCH:
            return NAME_5_WAY_SWITCH
        if (self.dev_id & 0xFFFF) == PID_6_POS_DIP_SWITCH:
            return NAME_6_POS_DIP_SWITCH
        return "Invalid dev"

    def _set_mode(self, enable):
        if not self.dev_id:
            return None
        v = _CMD_BLOCK_DET_MODE
        if enable:
            v = _CMD_EVENT_DET_MODE
        self.bus.write_byte(self._addr, v)
        return True

    def read(self):
        '''
        Get the button array status

        Returns:
            (list): a list has the size button count + 1
                    item [0] indicate if there is a event (bit 0x80).
                        bit 0x80 set if one or more the switches have event.
                        bit 0x80 clear if no one has event.
                    item [ 1 + `index` ] indicate the event of button specified
                        by index, be bits combination of

                              -  Button.EV_LEVEL_CHANGED
                              -  Button.EV_SINGLE_CLICK
                              -  Button.EV_DOUBLE_CLICK
                              -  Button.EV_LONG_PRESS

        '''
        EVT_LEN = 4
        if not self.dev_id:
            return None
        size = EVT_LEN + self._size
        v = self.bus.read_i2c_block_data(self._addr, _CMD_GET_DEV_EVENT, size)

        if self._version > 1 or self.__last_evt is None:
            return v[EVT_LEN - 1:]

        # Fix: v0.1 will miss event BTN_EV_LEVEL_CHANGED
        #      if this API called frequently.
        for i in range(self._size):
            if (v[EVT_LEN + i] ^ self.__last_evt[1 + i]) & self.EV_RAW_STATUS:
                v[EVT_LEN + i] |= Button.EV_LEVEL_CHANGED
                v[EVT_LEN - 1] |= 0x80
        self.__last_evt = v[EVT_LEN - 1:]
        return v[EVT_LEN - 1:]

    def is_pressed(self, index=0):
        '''
        Get the button status if it's being pressed ?

        :class:`ButtonTypedI2c.read` must be called before this api call
        when used with poll method object (created with evt_en = False).

        Args:
            index(int): optional, the index number of button to be checked.
                        must be specified for this device.

        Returns:
            (bool):
                True if the button is being pressed.
                False if not.
        '''
        return not bool(self.__last_evt[index + 1] & self.EV_RAW_STATUS)
示例#2
0
class ButtonTypedI2c(Button):
    def __init__(self, address=0x03):
        self.bus = Bus()
        self.addr = address
        self.dev_id = 0
        self.val = 0
        self.probeDevID()
        self.get_val()
        self.send_Byte(0x02)
        app1 = self.status_read()
        while 1:
            self.status_read()
            time.sleep(1.0)
            continue

    def set_devID(self, reg, size):
        self.bus.write_byte_data(self.addr, reg, size)

    def send_Byte(self, reg):
        self.bus.write_byte(self.addr, reg)

    def get_devID(self, data):
        return self.bus.read_byte(self.addr, data)

    def get_data(self, reg, len):
        return self.bus.read_i2c_block_data(self.addr, reg, len)

    def probeDevID(self):
        for i in range(4):
            id = self.get_data(0x00, 4)
            did = 0
            for j in range(4):
                did = (did >> 8) | (int(id[j]) << 24)
            #print("DEV_ID = {:8X}".format(did))
            if (did >> 16) == 0x2886:
                self.dev_id = did
                return self.dev_id
            self.get_devID(True)

    def get_val(self):
        if (self.dev_id & 0xFFFF) == 0x0002:
            self.val = 5
            print("Grove 5_way tactile Switch Insert")
            self.key_names = grove_5way_tactile_keys
            return self.val
        elif (self.dev_id & 0xFFFF) == 0x0003:
            self.val = 6
            print("Grove 6_pos dip Switch Insert")
            self.key_names = grove_6pos_dip_switch_keys
            return self.val

    def status_read(self):
        app = self.get_data(0x01, 4 + self.val)
        #print("get event ={}".format(app))
        for i in range(0, self.val):
            print("{} : RAW- ".format(self.key_names[i]), end='')
            print("{} ".format(app[i + 4] & 1 and "HIGH" or "LOW"))
            if (self.dev_id & 0xFFFF) == 0x0002:
                print("{} ".format(app[i + 4] & 1 and "RELEASEND"
                                   or "PRESSED"))
            elif (self.dev_id & 0xFFFF) == 0x0003:
                print("{} ".format(app[i + 4] & 1 and "OFF" or "ON"))
        for i in range(0, self.val):
            if app[i + 4] & ~1:
                print("{} ".format(self.key_names[i]))
                print(": EVENT - ")
            if app[i + 4] & (1 << 1):
                print("SINGLE-CLICK")
            if app[i + 4] & (1 << 2):
                print("DOUBLE-CLICL")
            if app[i + 4] & (1 << 3):
                print("LONG-PRESS")
            if app[i + 4] & (1 << 4):
                print("LEVEL-CHANGED")

            print("")
        return app