예제 #1
0
    def open(self):
        """Open a connection to the I2C bus.

        :raises: raspy.object_disposed_exception.ObjectDisposedException if
        this instance has been disposed.

        :raises: raspy.io.io_exception.IOException if unable to open the
        bus connection.
        """
        if self.is_disposed:
            raise ObjectDisposedException("I2CBus")

        if self.__isOpen:
            return

        try:
            self.__bus = SMBus(self.__busID)
        except OSError or IOError:
            msg = "Error opening bus '" + str(self.__busID) + "'."
            raise IOException(msg)

        if self.__bus.fd is None:
            msg = "Error opening bus '" + str(self.__busID) + "'."
            raise IOException(msg)

        self.__isOpen = True
예제 #2
0
    def __read(self, register):
        """Read a single byte from the specified register.

        :param int register: The register to write to. This should be one of
        the register constants.
        :returns: The byte read.
        :rtype: int
        :raises: raspy.io.io_exception.IOException if unable to read from
        the SPI bus.
        """
        # create packet in data buffer.
        packet = [
            self.__address | self.RD_FLAG,  # address byte
            register,  # register byte
            0x00000000  # data byte
        ]

        result = 0
        try:
            temp = self.__spi.xfer(packet, self.__speed)
            if temp is not None:
                result = temp[2] & 0xFF
        except (IOError, SystemError, RuntimeError) as ex:
            err_msg = "Failed to write to SPI bus device at address "
            err_msg += str(self.__address) + " on channel /dev/spidev0.0"
            err_msg += str(ex)
            raise IOException(err_msg)

        return result
예제 #3
0
    def read_gyro(self):
        """Read the gyro and store the value internally.

        :raise: raspy.object_disposed_exception.ObjectDisposedException if
        this instance has been disposed.

        :raises: raspy.io.io_exception.IOException if unable to write to the
        gyro.
        """
        if self.is_disposed:
            raise ObjectDisposedException("ADXL345")

        now = system_info.get_current_time_millis()
        self.__timeDelta = now - self.__lastRead
        self.__lastRead = now

        self.__device.write_byte(self.__address, 0x00)
        core_utils.sleep(10)
        data = self.__device.read_bytes(self.__address, 6)
        if len(data) != 6:
            msg = "Couldn't read compass data; Return buffer size: "
            msg += str(len(data))
            raise IOException(msg)

        self.a_x.raw_value = ((data[0] & 0xff) << 8) + (data[1] & 0xff)
        self.a_y.raw_value = ((data[2] & 0xff) << 8) + (data[3] & 0xff)
        self.a_z.raw_value = ((data[3] & 0xff) << 8) + (data[5] & 0xff)
예제 #4
0
    def device_status(self):
        """Get the device status.

        :returns: The device status.
        :rtype: DeviceControllerStatus
        :raises: raspy.io.io_exception.IOException if status bits 4 to 8 are
        not set to 1.
        """
        # Get status from device.
        stat = self._read(MEMADDR_STATUS)

        # Check formal criteria.
        reserved = stat & status_bit.RESERVED_MASK
        if reserved != status_bit.RESERVED_VALUE:
            msg = "Status bits 4 to 8 must be 1 according to documentation "
            msg += "chapter 4.2.2.1. Got: " + str(reserved)
            raise IOException(msg)

        # Build the result.
        eeprom_write_active = (stat & status_bit.EEPROM_WRITE_ACTIVE) > 0
        eeprom_write_prot = (stat & status_bit.EEPROM_WRITE_PROTECTION) > 0
        wiper_lock0 = (stat & status_bit.WIPER_LOCK0) > 0
        wiper_lock1 = (stat & status_bit.WIPER_LOCK1) > 0
        return DeviceControllerStatus(eeprom_write_active, eeprom_write_prot,
                                      wiper_lock0, wiper_lock1)
예제 #5
0
    def _read(self, mem_addr):
        """Read 2 bytes from the device at the given memory address.

        :param int mem_addr: The memory address to read from.
        :returns: The 2 bytes read.
        :rtype: int
        :raises: raspy.io.io_exception.IOException if communication failed
        - or - device returned a malformed result.
        """
        # Command to ask device for reading data.
        cmd = (mem_addr << 4) | mcp_command.READ
        self.__device.write_byte(self.__busAddress, cmd)

        # Read 2 bytes.
        buf = self.__device.read_bytes(self.__busAddress, 2)
        if len(buf) != 2:
            msg = "Malformed response. Expected to read 2 bytes but got: "
            msg += str(len(buf))
            raise IOException(msg)

        # Transform signed byte to unsigned byte stored as int.
        first = buf[0] & 0xFF
        second = buf[1] & 0xFF

        # Interpret both bytes as one integer.
        return (first << 8) | second
예제 #6
0
 def poll(self):
     """Execute pin polling on background thread."""
     ioEx = IOException("Poll failed.")
     self.__evt = PinPollFailEvent(ioEx)
     self.__pollThread = threading.Thread(target=self.on_poll_fail)
     self.__pollThread.name = "DummyEmitterThread"
     self.__pollThread.daemon = True
     self.__pollThread.start()
예제 #7
0
    def test_io_exception(self):
        """Test the exception."""
        caught = None
        try:
            raise IOException("This is a test.")
        except Exception as ex:
            caught = ex

        assert isinstance(caught, IOException)
예제 #8
0
    def delete(self):
        """Delete this file.

        :raises: raspy.io.io_exception.IOException if an error occurred while
        trying to delete the file (such as if the file does not exist).
        """
        try:
            if self.exists():
                os.remove(self.__fullPath)
        except OSError as ex:
            raise IOException(ex.strerror)
예제 #9
0
def write_fs_pin(pin_path, val_string):
    """Write the specified string to the specified pin.

    :param string pin_path: The full path to the pin to write to.
    :param string val_string: The value string to write to the pin.
    :raises: raspy.io.io_exception.IOException if an IOError occurred while
    accessing the pin.
    """
    try:
        target = open(pin_path, 'w')
        target.write(val_string)
        target.close()
    except IOError as ex:
        raise IOException(ex.strerror)
예제 #10
0
    def read_bytes(self, address, count):
        """Read bytes from the device at the specified address.

        :param int address: The address of the device to read from.
        :param int count: The number of bytes to read.
        :returns: The bytes read.
        :rtype: list
        :raises: raspy.object_disposed_exception.ObjectDisposedException if
        this instance has been disposed.

        :raises: raspy.invalid_operation_exception.InvalidOperationException if
        a connection to the I2C bus has not yet been opened.

        :raises: raspy.io.io_exception.IOException if an error occurs while
        writing the buffer contents to the I2C bus or if only a partial
        write succeeds.
        """
        if self.is_disposed:
            return

        if not self.__isOpen:
            raise InvalidOperationException("No open connection to read from.")

        buf = []
        msg = "Error reading from address '" + str(address)
        msg += "': I2C transaction failed."
        try:
            trans = i2c_msg.read(address, count)
            self.__bus.i2c_rdwr(trans)
            buf = list(trans)
        except OSError or IOError:
            raise IOException(msg)

        if len(buf) <= 0:
            raise IOException(msg)

        return buf
예제 #11
0
    def write_bytes(self, address, buf):
        """Write a list of bytes to the specified device address.

        Currently, RPi drivers do not allow writing more than 3 bytes at a
        time. As such, if any list of greater than 3 bytes is provided, an
        exception is thrown.

        :param int address: The address of the target device.
        :param list buf: A list of bytes to write to the bus.
        :raises: raspy.object_disposed_exception.ObjectDisposedException if
        this instance has been disposed.

        :raises: raspy.invalid_operation_exception.InvalidOperationException if
        a connection to the I2C bus has not yet been opened.

        :raises: raspy.illegal_argument_exception.IllegalArgumentException if
        the buffer contains more than 3 bytes or if the specified buffer
        parameter is not a list.

        :raises: raspy.io.io_exception.IOException if an error occurs while
        writing the buffer contents to the I2C bus or if only a partial
        write succeeds.
        """
        if self.is_disposed:
            raise ObjectDisposedException("I2CBus")

        if not self.__isOpen:
            raise InvalidOperationException("No open connection to write to.")

        if isinstance(buf, list):
            if len(buf) > 3:
                # TODO we only do this to keep parity with the JS and C#
                # ports. They each have their own underlying native
                # implementations. SMBus2 itself is capable of writing
                # much more than 3 bytes. We should change this as soon
                # as we can get the other ports to support more.
                msg = "Cannot write more than 3 bytes at a time."
                raise IllegalArgumentException(msg)
        else:
            msg = "The specified buf param value is not a list."
            raise IllegalArgumentException(msg)

        try:
            trans = i2c_msg.write(address, buf)
            self.__bus.i2c_rdwr(trans)
        except OSError or IOError:
            msg = "Error writing to address '" + str(address)
            msg += "': I2C transaction failed."
            raise IOException(msg)
예제 #12
0
def read_fs_pin(pin_path):
    """Read the value from the specified pin.

    :param string pin_path: The full path to the pin to write to.
    :returns: The value read from the pin.
    :rtype: int
    :raises: raspy.io.io_exception.IOException if an IOError occurred while
    accessing the pin.
    """
    try:
        target = open(pin_path, 'r')
        read_string = target.read()
        val = int(read_string[0:1])
        target.close()
    except IOError as ex:
        raise IOException(ex.strerror)

    return val
예제 #13
0
    def __write(self, register, data):
        """Write the specified byte to the specified register.

        :param int register: The register to write to. This should be one of
        the register constants.
        :param int data: A single byte to write to the register.
        :raises: raspy.io.io_exception.IOException if unable to write to the
        SPI bus.
        """
        # create packet in data buffer.
        packet = [
            self.__address | self.WRT_FLAG,  # address byte
            register,  # register byte
            data  # data byte
        ]

        try:
            self.__spi.writebytes(packet)
        except (IOError, SystemError, RuntimeError) as ex:
            err_msg = "Failed to write to SPI bus device at address "
            err_msg += str(self.__address) + " on channel /dev/spidev0.0"
            err_msg += str(ex)
            raise IOException(err_msg)
예제 #14
0
    def __internal_read(self, gpio_num, gpio_name):
        """Read the value of the specified GPIO pin.

        :param str gpio_num: The GPIO pin number.
        :param str gpio_name: The name of the GPIO.
        :returns: The value of the pin.
        :rtype: int
        :raises: raspy.io.io_exception.IOException if the specified pin could
        not be read (device does not exist).
        """
        return_value = pin_state.LOW
        self.__internal_export_pin(pin_mode.IN, gpio_num, gpio_name)
        file_name = IO_PATH + "gpio" + gpio_num + "/value"
        if os.path.exists(file_name):
            read_value = pin_utils.read_fs_pin(file_name)
            if read_value == 1:
                return_value = pin_state.HIGH
        else:
            err_msg = "Cannot read from pin " + gpio_num + ". "
            err_msg += "Device does not exist"
            raise IOException(err_msg)

        return return_value
예제 #15
0
    def __init__(self, pn, initial_val, spi_address, spi_speed):
        """Initialize a new instance of the raspy.io.pi_face_gpio_digital.PiFaceGpioDigital class.

        :param raspy.io.pi_face_pins.PiFacePin pn: The PiFace pin to control.
        :param int initial_val: The initial value (state) to set the pin to.
        Default is PinState.LOW.
        :param int spi_address: The SPI address to use. (Should be ADDRESS_0,
        ADDRESS_1, ADDRESS_2, or ADDRESS_3).
        :param int spi_speed: The clock speed to set the bus to. Can be powers
        of 2 (500KHz minimum up to 32MHz maximum). If not specified, the
        default of SPI_SPEED (1MHz) will be used.
        :raises: raspy.io.io_exception.IOException if unable to read or write
        to the SPI bus.
        """
        PiFaceGPIO.__init__(self, pn, initial_val, pn.name)

        if spi_speed is None or not isinstance(spi_speed, (int, long)):
            spi_speed = self.BUS_SPEED

        self.__speed = spi_speed
        self.__spi = SpiDev()
        try:
            self.__spi.open(0, 0)
        except Exception:
            raise IOException("Unable to open SPI device 0 on bus 0.")

        self.__spi.max_speed_hz = self.__speed
        self.__address = self.DEF_ADDR
        if spi_address is not None:
            self.__address = spi_address

        self.__currentStatesA = 0x00000000
        self.__currentStatesB = 0x11111111
        self.__currentDirectionA = 0x00000000
        self.__currentDirectionB = 0x11111111
        self.__currentPullupA = 0x00000000
        self.__currentPullupB = 0x11111111
        self.__oldState = pin_state.LOW
        self.__pullResistance = pin_pull_resistance.Off
        self.__pollThread = None
        self.__pollRunning = False
        self.__stopEvent = threading.Event()
        self.__stopEvent.set()

        # IOCON - I/O EXPANDER CONFIGURATION REGISTER
        #
        # bit 7 BANK: Controls how the registers are addressed
        #     1 = The registers associated with each port are separated into
        # different banks
        # 0 = The registers are in the same bank (addresses are sequential)
        # bit 6 MIRROR: INT Pins Mirror bit
        # 1 = The INT pins are internally connected
        # 0 = The INT pins are not connected. INTA is associated with PortA and
        # INTB is associated with PortB
        # bit 5 SEQOP: Sequential Operation mode bit.
        # 1 = Sequential operation disabled, address pointer does not
        # increment.
        # 0 = Sequential operation enabled, address pointer increments.
        # bit 4 DISSLW: Slew Rate control bit for SDA output.
        # 1 = Slew rate disabled.
        # 0 = Slew rate enabled.
        # bit 3 HAEN: Hardware Address Enable bit (MCP23S17 only).
        # Address pins are always enabled on MCP23017.
        # 1 = Enables the MCP23S17 address pins.
        # 0 = Disables the MCP23S17 address pins.
        # bit 2 ODR: This bit configures the INT pin as an open-drain output.
        # 1 = Open-drain output (overrides the INTPOL bit).
        # 0 = Active driver output (INTPOL bit sets the polarity).
        # bit 1 INTPOL: This bit sets the polarity of the INT output pin.
        # 1 = Active-high.
        # 0 = Active-low.
        # bit 0 Unimplemented: Read as '0'.
        #

        # write io configuration. enable hardware address.
        self.__write(self.REGISTER_IOCON_A, self.IOCON_SEQOP | self.IOCON_HAEN)
        self.__write(self.REGISTER_IOCON_B, self.IOCON_SEQOP | self.IOCON_HAEN)

        # read initial GPIO pin states
        self.__currentStatesA = self.__read(self.REGISTER_GPIO_A)
        self.__currentStatesB = self.__read(self.REGISTER_GPIO_B)

        # set all default pin pull up resistors
        # (1 = Pull-up enabled.)
        # (0 = Pull-up disabled.)
        self.__write(self.REGISTER_IODIR_A, self.__currentDirectionA)
        self.__write(self.REGISTER_IODIR_B, self.__currentDirectionB)

        # set all default pin states
        self.__write(self.REGISTER_GPIO_A, self.__currentStatesA)
        self.__write(self.REGISTER_GPIO_B, self.__currentStatesB)

        # set all default pin pull up resistors
        # (1 = Pull-up enabled.)
        # (0 = Pull-up disabled.)
        self.__write(self.REGISTER_GPPU_A, self.__currentPullupA)
        self.__write(self.REGISTER_GPPU_B, self.__currentPullupB)

        # set all default pin interrupts
        # (if pin direction is input (1), then enable interrupt for pin)
        # (1 = Enable GPIO input pin for interrupt-on-change event.)
        # (0 = Disable GPIO input pin for interrupt-on-change event.)
        self.__write(self.REGISTER_GPINTEN_A, self.__currentDirectionA)
        self.__write(self.REGISTER_GPINTEN_B, self.__currentDirectionB)

        # set all default pin interrupt default values
        # (comparison value registers are not used in this implementation)
        self.__write(self.REGISTER_DEFVAL_A, 0x00)
        self.__write(self.REGISTER_DEFVAL_B, 0x00)

        # set all default pin interrupt comparison behaviors
        # (1 = Controls how the associated pin value is compared for
        # interrupt-on-change.)
        # (0 = Pin value is compared against the previous pin value.)
        self.__write(self.REGISTER_INTCON_A, 0x00)
        self.__write(self.REGISTER_INTCON_B, 0x00)

        # reset/clear interrupt flags
        if self.__currentDirectionA > 0:
            self.__read(self.REGISTER_INTCAP_A)

        if self.__currentDirectionB > 0:
            self.__read(self.REGISTER_INTCAP_B)