Source

pylibftdi / pylibftdi / bitbang.py

Ben Bass fc1c7d7 


Ben Bass 67e4b88 
Ben Bass fc1c7d7 




Ben Bass e119a40 
Ben Bass 39d7d10 
Ben Bass 70d5028 
Ben Bass e119a40 





Ben Bass fed55e4 
Ben Bass eea1286 
Ben Bass e119a40 

Ben Bass 41cf71e 
Ben Bass 70d5028 



Ben Bass 41cf71e 
Ben Bass e119a40 



Ben Bass bce2b77 
Ben Bass fed55e4 

Ben Bass 70d5028 
Ben Bass 927fe8f 

Ben Bass 3262110 

Ben Bass 92491bf 



Ben Bass fed55e4 

Ben Bass 927fe8f 
Ben Bass 3262110 

Ben Bass e119a40 
Ben Bass 70d5028 
Ben Bass 927fe8f 
Ben Bass 8774aac 
Ben Bass 0d801d4 



Ben Bass 92491bf 

Ben Bass e119a40 

Ben Bass fc1c7d7 
Ben Bass e119a40 

Ben Bass eea1286 
Ben Bass 92491bf 
Ben Bass e119a40 


Ben Bass 0d801d4 

































Ben Bass e119a40 



Ben Bass fc1c7d7 



Ben Bass e119a40 
Ben Bass 41cf71e 
Ben Bass e119a40 

Ben Bass 92491bf 

Ben Bass e119a40 
Ben Bass 8a50442 
Ben Bass 927fe8f 
Ben Bass 8774aac 
Ben Bass e119a40 



Ben Bass fc1c7d7 




Ben Bass bd593a0 



Ben Bass 70d5028 
Ben Bass bd593a0 






Ben Bass 70d5028 
Ben Bass bd593a0 




Ben Bass e119a40 
Ben Bass 41cf71e 
Ben Bass e119a40 


Ben Bass 70d5028 

Ben Bass eea1286 
"""
pylibftdi - python wrapper for libftdi

Copyright (c) 2010-2013 Ben Bass <benbass@codedstructure.net>
See LICENSE file for details and (absence of) warranty

pylibftdi: http://bitbucket.org/codedstructure/pylibftdi

"""

from pylibftdi.driver import Device, FtdiError, BITMODE_BITBANG
from ctypes import c_ubyte, byref

ALL_OUTPUTS = 0xFF
ALL_INPUTS = 0x00
BB_OUTPUT = 1
BB_INPUT = 0


class BitBangDevice(Device):
    """
    simple subclass to support bit-bang mode

    Internally uses async mode at the moment, but provides a 'sync'
    flag (defaulting to True) which controls the behaviour of port
    reading and writing - if set, the FIFOs are ignored (read) or
    cleared (write) so operations will appear synchronous

    Adds two read/write properties to the base class:
     direction: 8 bit input(0)/output(1) direction control.
     port: 8 bit IO port, as defined by direction.
    """
    def __init__(self,
                 device_id=None,
                 direction=ALL_OUTPUTS,
                 lazy_open=False,
                 sync=True,
                 bitbang_mode=BITMODE_BITBANG,
                 interface_select=None,
                 **kwargs):
        # initialise the super-class, but don't open yet. We really want
        # two-part initialisation here - set up all the instance variables
        # here in the super class, then open it after having set more
        # of our own variables.
        super(BitBangDevice, self).__init__(device_id=device_id,
                                            mode='b',
                                            lazy_open=True,
                                            interface_select=interface_select,
                                            **kwargs)
        self.direction = direction
        self.sync = sync
        self.bitbang_mode = bitbang_mode
        self._last_set_dir = None
        # latch is the latched state of output pins.
        # it is initialised to the read value of the pins
        # 'and'ed with those bits set to OUTPUT (1)
        self._latch = None
        if not lazy_open:
            self.open()

    def open(self):
        "open connection to a FTDI device"
        # in case someone sets the direction before we are open()ed,
        # we intercept this call...
        super(BitBangDevice, self).open()
        if self.direction != self._last_set_dir:
            self.direction = self._direction
        return self

    def read_pins(self):
        """
        read the current 'actual' state of the pins

        :return: 8-bit binary representation of pin state
        :rtype: int
        """
        pin_byte = c_ubyte()
        res = self.ftdi_fn.ftdi_read_pins(byref(pin_byte))
        if res != 0:
            raise FtdiError("Could not read device pins")
        return pin_byte.value

    @property
    def latch(self):
        """
        latch property - the output latch (in-memory representation
        of output pin state)

        Note _latch is not masked by direction (except on initialisation),
        as otherwise a loop incrementing a mixed input/output port would
        not work, as it would 'stop' on input pins. This is the primary
        use case for 'latch'. It's basically a `port` which ignores input.

        :return: the state of the output latch
        """
        if self._latch is None:
            self._latch = self.read_pins() & self.direction
        return self._latch

    @latch.setter
    def latch(self, value):
        self.port = value  # this updates ._latch implicitly

    # direction property - 8 bit value determining whether an IO line
    # is output (if set to 1) or input (set to 0)
    @property
    def direction(self):
        """
        get or set the direction of each of the IO lines. LSB=D0, MSB=D7
        1 for output, 0 for input
        """
        return self._direction

    @direction.setter
    def direction(self, dir):
        if not (0 <= dir <= 255):
            raise FtdiError("invalid direction bitmask")
        self._direction = dir
        if not self.closed:
            self.ftdi_fn.ftdi_set_bitmode(dir, self.bitbang_mode)
            self._last_set_dir = dir

    # port property - 8 bit read/write value
    @property
    def port(self):
        """
        get or set the state of the IO lines.  The value of output
        lines is persisted in this object for the purposes of reading,
        so read-modify-write operations (e.g. drv.port+=1) are valid.
        """
        if self._direction == ALL_OUTPUTS:
            # a minor optimisation; no point reading from the port if
            # we have no input lines set
            result = self.latch
        else:
            if self.sync:
                result = self.read_pins()
            else:
                # the coercion to bytearray here is to make this work
                # transparently between Python2 and Python3 - equivalent
                # of ord() for Python2, a time-wasting do-nothing on Python3
                result = bytearray(super(BitBangDevice, self).read(1))[0]

            # replace the 'output' bits with current value of self.latch -
            # the last written value. This makes read-modify-write
            # operations (e.g. 'drv.port |= 0x10') work as expected
            result = ((result & ~self._direction) |    # read input
                      (self.latch & self._direction))  # output latch
        return result

    @port.setter
    def port(self, value):
        self._latch = value
        if self.sync:
            self.flush_output()
        return super(BitBangDevice, self).write(chr(value))
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.