Commits

Ben Bass committed 41cf71e

updated to 0.6 - support for Python 3

Comments (0)

Files changed (12)

 pylibftdi changes
 =================
 
+0.6
+ * same source now works on both Python2.6+ and Python3.
 0.5
  * fix various bugs found by pyflakes
  * improve module organisation, while providing interface compatibility
-Copyright (c) 2010 Ben Bass
+Copyright (c) 2010-2011 Ben Bass
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 
 
 
-http://www.opensource.org/licenses/mit-license.php
+http://www.opensource.org/licenses/mit-license.php
+Metadata-Version: 1.0
+Name: pylibftdi
+Version: 0.6
+Summary: Pythonic interface to FTDI devices using libftdi
+Home-page: http://bitbucket.org/codedstructure/pylibftdi
+Author: Ben Bass
+Author-email: benbass@codedstructure.net
+Description: pylibftdi is a minimal Pythonic interface to FTDI devices using libftdi.
+        The primary interface is the ``Driver`` class in the pylibftdi package; this
+        gives serial access on relevant FTDI devices (e.g. the UM232R), providing a
+        file-like interface (read, write).  Baudrate is controlled with the ``baudrate``
+        property.
+
+        If a Driver instance is created with ``mode='t'`` (text mode) then read() and
+        write() can use the given ``encoding`` (defaulting to latin-1). This doesn't
+        make a lot of difference on Python 2, but allows easier integration with passing
+        unicode strings between devices in Python 3.
+
+        For example::
+        
+            >>> with Driver(mode='t') as drv:
+            >>>     drv.baudrate = 115200
+            >>>     drv.write('Hello World')
+
+        The pylibftdi.BitBang wrapper provides access to the parallel IO mode of operation
+        through the ``port`` and ``direction`` properties.  These provide an 8 bit IO port
+        including all the relevant bit operations to make things simple.
+
+        
+            >>> with BitBang() as bb:
+            >>>     bb.direction = 0x0F   # four LSB are output(1), four MSB are input(0).
+            >>>     bb.port |= 2          # set bit 1
+            >>>     bb.port &= 0xFE       # clear bit 0
+
+Keywords: console,interpreter,expressions
+Platform: UNKNOWN
+Classifier: Development Status :: 4 - Beta
+Classifier: Environment :: Console
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.0
+Classifier: Programming Language :: Python :: 3.1
+Classifier: Programming Language :: Python :: 3.2
+Classifier: Operating System :: Microsoft :: Windows
+Classifier: Operating System :: POSIX
+Classifier: Topic :: Scientific/Engineering
+Classifier: Topic :: Software Development :: Embedded Systems
+Classifier: Topic :: System :: Hardware
 pylibftdi
 =========
 
-Copyright (c) 2010 Ben Bass <benbass@codedstructure.net>
+Copyright (c) 2010-2011 Ben Bass <benbass@codedstructure.net>
 
 All rights reserved.
 
 >   sleep 5;
 > done
 
-Copyright (c) 2010 Ben Bass <benbass@codedstructure.net>
+Copyright (c) 2010-2011 Ben Bass <benbass@codedstructure.net>
 All rights reserved.
 """
 
 def display(string):
     "Display the given string on an attached LCD"
     with BitBangDriver() as bb:
-    
+
         # These LCDs are quite slow - and the actual baudrate
         # is 16x this in bitbang mode...
         bb.baudrate = 60
 
         lcd = LCD(bb)
         lcd.init_four_bit()
-    
+
         # 001xxxxx - function set
         lcd.write_cmd(0x20)
         # 00000001 - clear display
         # bit 1: display cursor
         # bit 0: blinking cursor
         lcd.write_cmd(0x0C)
-    
+
         for i in string:
             lcd.write_data(ord(i))
 
     if len(sys.argv) == 2:
         display(sys.argv[1])
     else:
-        print "Usage: %s 'display string'"
+        print("Usage: %s 'display string'")

examples/led_flash.py

 """
 Flash an LED connected via a FTDI UM232R/245R module using pylibftdi
 
-Copyright (c) 2010 Ben Bass <benbass@codedstructure.net>
+Copyright (c) 2010-2011 Ben Bass <benbass@codedstructure.net>
 All rights reserved.
 """
 
+import time
 from pylibftdi import BitBangDriver
 
-import time
-
 def flash_forever(rate):
     "toggle bit zero at rate Hz"
     # put an LED with 1Kohm or similar series resistor
             bb.port ^= 1
 
 if __name__ == '__main__':
-    flash_forever(1)
+    flash_forever(1)

pylibftdi/__init__.py

 """
 pylibftdi - python wrapper for libftdi
 
-Copyright (c) 2010 Ben Bass <benbass@codedstructure.net>
+Copyright (c) 2010-2011 Ben Bass <benbass@codedstructure.net>
 See LICENSE file for details and (absence of) warranty
 
 pylibftdi: http://bitbucket.org/codedstructure/pylibftdi
 rather than a problem with the libftdi library.
 """
 
-__VERSION__ = "0.5"
+__VERSION__ = "0.6"
 __AUTHOR__ = "Ben Bass"
 
 

pylibftdi/_base.py

 """
 pylibftdi - python wrapper for libftdi
 
-Copyright (c) 2010 Ben Bass <benbass@codedstructure.net>
+Copyright (c) 2010-2011 Ben Bass <benbass@codedstructure.net>
 See LICENSE file for details and (absence of) warranty
 
 pylibftdi: http://bitbucket.org/codedstructure/pylibftdi

pylibftdi/bitbang.py

 """
 pylibftdi - python wrapper for libftdi
 
-Copyright (c) 2010 Ben Bass <benbass@codedstructure.net>
+Copyright (c) 2010-2011 Ben Bass <benbass@codedstructure.net>
 See LICENSE file for details and (absence of) warranty
 
 pylibftdi: http://bitbucket.org/codedstructure/pylibftdi
 class BitBangDriver(Driver):
     """
     simple subclass to support bit-bang mode
-    
+
     Only uses async mode at the moment.
-    
+
     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, direction = ALL_OUTPUTS):
-        super(BitBangDriver, self).__init__()
+        super(BitBangDriver, self).__init__(mode = 'b')
         self.direction = direction
         self._latch = 0
 
             self.direction = self._direction
         return self
 
+
     # direction property - 8 bit value determining whether an IO line
     # is output (if set to 1) or input (set to 0)
     @property
         1 for output, 0 for input
         """
         return self._direction
+
     @direction.setter
     def direction(self, dir):
         assert 0 <= dir <= 255, 'invalid direction bitmask'
         if self.opened:
             self.fdll.ftdi_set_bitmode(byref(self.ctx), dir, 0x01)
 
+
     # port property - 8 bit read/write value
     @property
     def port(self):
         lines is persisted in this object for the purposes of reading,
         so read-modify-write operations (e.g. drv.port+=1) are valid.
         """
-        result = ord(super(BitBangDriver, self).read(1)[0])
+        # 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(BitBangDriver, self).read(1))[0]
         # replace the 'output' bits with current value of _latch -
         # the last written value. This makes read-modify-write
         # operations (e.g. 'drv.port |= 0x10') work as expected
         result = (result & ~self._direction) | (self._latch & self._direction)
         return result
+
     @port.setter
     def port(self, value):
         self._latch = value

pylibftdi/driver.py

 """
 pylibftdi - python wrapper for libftdi
 
-Copyright (c) 2010 Ben Bass <benbass@codedstructure.net>
+Copyright (c) 2010-2011 Ben Bass <benbass@codedstructure.net>
 See LICENSE file for details and (absence of) warranty
 
 pylibftdi: http://bitbucket.org/codedstructure/pylibftdi
     This is where it all happens...
     We load the libftdi library, and use it.
     """
-    def __init__(self):
+    def __init__(self, mode="b", encoding="latin1"):
         self.ctx = None
         self.fdll = ParrotEgg()
         self.opened = False
+        # mode can be either 'b' for binary, or 't' for text.
+        # if set to text, the values returned from read() will
+        # be decoded using encoding before being returned as
+        # strings; for binary the raw bytes will be returned.
+        # This will only affect Python3.
+        self.mode = mode
+        # when giving a str to Driver.write(), it is encoded.
+        # default is latin1, because it provides
+        # a one-to-one correspondence for code points 0-FF
+        self.encoding = encoding
         # ftdi_usb_open_dev initialises the device baudrate
         # to 9600, which certainly seems to be a de-facto
         # standard for serial devices.
     def open(self):
         "open connection to a FTDI device"
         if self.opened:
-            return self
+            return
         # TODO: provide parameter to select required device
         # (if multiple are attached)
         ftdi_lib = find_library('ftdi')
         #   (except we don't have deterministic destructors. oh well.)
         self.fdll = fdll
         self.opened = True
-        return self
 
     def close(self):
         "close our connection, free resources"
             self.fdll.ftdi_deinit(byref(self.ctx))
         self.fdll = DeadParrot()
 
+
     @property
     def baudrate(self):
         """
         to ensure baudrate was accepted by the driver.
         """
         return self._baudrate
+
     @baudrate.setter
     def baudrate(self, value):
         result = self.fdll.ftdi_set_baudrate(byref(self.ctx), value)
         if result == 0:
             self._baudrate = value
 
+
     def read(self, length):
-        "read a string of upto length bytes from the FTDI device"
+        """
+        read upto length bytes from the FTDI device
+        return type depends on self.mode - if 'b' return
+        raw bytes, else decode according to self.encoding
+        """
         buf = create_string_buffer(length)
         rlen = self.fdll.ftdi_read_data(byref(self.ctx), byref(buf), length)
         if rlen == -1:
             raise FtdiError(self.get_error_string())
-        return buf.raw[:rlen]
+        byte_data = buf.raw[:rlen]
+        if self.mode == 'b':
+            return byte_data
+        else:
+            return byte_data.decode(self.encoding)
 
     def write(self, data):
         "write given data string to the FTDI device"
-        buf = create_string_buffer(data)
+        try:
+            byte_data = bytes(data)
+        except TypeError:
+            # this will happen if we are Python3 and data is a str.
+            byte_data = data.encode(self.encoding)
+        buf = create_string_buffer(byte_data)
         written = self.fdll.ftdi_write_data(byref(self.ctx),
                                             byref(buf), len(data))
         if written == -1:
             raise FtdiError(self.get_error_string())
         return written
 
+
     def get_error_string(self):
         "return error string from libftdi driver"
         return self.fdll.ftdi_get_error_string(byref(self.ctx))
 
+
     @property
     def ftdi_fn(self):
         """
         which are called with a pointer to a ftdi_context
         struct as the first parameter to be called here
         in a nicely encapsulated way:
-        >>> with FtdiDriver() as drv:
+        >>> with Driver() as drv:
         >>>     # set 8 bit data, 2 stop bits, no parity
         >>>     drv.ftdi_fn.ftdi_set_line_property(8, 2, 0)
         >>>     ...
                                           byref(self.ctx))
         return FtdiForwarder()
 
+
     def __enter__(self):
-        "support for context manager"
-        return self.open()
+        """
+        support for context manager.
+        Note the driver is opened and closed automatically
+        when used in a with statement, and the driver object
+        itself is returned:
+        >>> with Driver(mode='t') as drv:
+        >>>     drv.write('Hello World!')
+        >>>
+        """
+        self.open()
+        return self
 
     def __exit__(self, exc_type, exc_val, tb):
         "support for context manager"

pylibftdi/util.py

 """
 pylibftdi - python wrapper for libftdi
 
-Copyright (c) 2010 Ben Bass <benbass@codedstructure.net>
+Copyright (c) 2010-2011 Ben Bass <benbass@codedstructure.net>
 See LICENSE file for details and (absence of) warranty
 
 pylibftdi: http://bitbucket.org/codedstructure/pylibftdi
     assert test_bus.c == 21
 
 if __name__ == '__main__':
-    test_bus_class()
+    test_bus_class()
 
 setup(
     name="pylibftdi",
-    version="0.5",
+    version="0.6",
     description="Pythonic interface to FTDI devices using libftdi",
     author="Ben Bass",
     author_email="benbass@codedstructure.net",
         "Operating System :: Microsoft :: Windows",
         "Operating System :: POSIX",
         "Programming Language :: Python",
+        "Programming Language :: Python :: 2.6",
+        "Programming Language :: Python :: 2.7",
+        "Programming Language :: Python :: 3",
         "Topic :: Scientific/Engineering",
         "Topic :: Software Development :: Embedded Systems",
         "Topic :: System :: Hardware"