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
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
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)
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)
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
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()
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)
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)
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)
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
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)
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
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)
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
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)