Am 02.05.2012 19:40, schrieb Petr Jakes:
Hi,
I am trying to work with HW peripherals on Raspberry Pi
To achieve this, it is necessary read/write some values from/to the
memory directly.

I am looking for some wise way how to organize the bit twiddling.

To set some specific bit, for example, it is necessary:
     - read 4 bytes string representation (I am using mmap)
     - transform it to the corresponding integer (I am using numpy)
     - do some bit masking over this integer
     - transport integer to the string representation (numpy again)
     - write it back to the memory

In other words I mean: is there wise way to create an instrument/
machinery to define Class and then simply define all necessary objects
and set the bit values over object attributes so the whole bit-
twiddling remains under the hood.

say:
LED01 = GPIO(4)  # gpio PIN number 4 is assigned to the LED01 name
(attribute)
LED01.on()
LED01.off()
  or

gpio = GPIO()
LED01 = gpio.pin04
LED01 = 1 # led diode is shining (or gpio pin 4 is set)
LED01 = 0 # led diode is off

I have an abstract BitVector base-class that allows to get/set single
bits or several bits in a convenient way.  You must define concrete
subclasses which define a _value get/set property that actually
updates the byte or word in the hardware.  I use it to access bits
or groups of bits of I2C devices.

You would basically code like this, assuming an 8-bit GPIO port:

class GPIO(BitVector):
    def __init__(self, address, value=0xFF, nbits=8):
        self.address = address
        super(GPIO, self).__init__(value, nbits)
    def _get_value(self):
        "read an 8-bit value from the hardware as 8-bit integer"
        ...
    def _set_value(self, v):
        "write the 8-bit value 'v' to the hardware"
        ...

then you can do:

gpio = GPIO(0x12345678)

led0 = gpio[4] # bit 4
led0.value = 1 # switch led on
print led0.value # get led status

For multiple bits use this (note that different from standard Python
practices, indexing works inclusive and uses [high_bitnum:low_bitnum]:

port = GPIO(0x12345678)
high_nibble = port[7:4]
print high_nibble.value
low_nibble = port[3:0]
low_nibble.value = 0xF

Thomas
class BitVector(object):
    """BitVector class, represents mutable integers
    constricted to a certain range.

    Single bits can be get/set by indexing with integers.

    Slices can be used to get/set the bits in this range, as an
    integer constricted to this range also.

    Slices must use [MSB:LSB], and are inclusive.

    >>> [x for x in BitVector(0xAA)]
    [0, 1, 0, 1, 0, 1, 0, 1]
    >>> [x for x in BitVector(0xFF)]
    [1, 1, 1, 1, 1, 1, 1, 1]
    >>>
    >>> bv = BitVector(0)
    >>> bv[6:3] = 0xf
    >>> [x for x in bv]
    [0, 0, 0, 1, 1, 1, 1, 0]
    >>> bv[6:3] = -1
    Traceback (most recent call last):
      ...
    ValueError: value out of allowed range
    >>> bv[6:3] = 16
    Traceback (most recent call last):
      ...
    ValueError: value out of allowed range
    >>> hex(bv)
    '0x78'
    >>> bin(bv)
    '0b1111000'
    >>> 
    """
    def __init__(self, value=0, nbits=8):
        self._nbits = nbits
        self._value = value

    def __index__(self):
        return self._value

    def __hex__(self):
        return hex(self._value)

    def __getitem__(self, index):
        if isinstance(index, slice):
            return self._getslice(index)
        if not 0 <= index < self._nbits:
            raise IndexError("invalid index")
        return int(bool(self._value & (1 << index)))

    @property
    def bits(self):
        """
        Return some bits as an object that has a .value property.  The
        .value property represents the current value of the specied
        bits.

        b = BitVector().bits[7:0]
        b.value = ...
        print b.value
        """
        class Bits(object):
            def __init__(self, bv):
                self.bv = bv
            def __getitem__(self, index):
                class GetSet(object):
                    def __init__(self, bv):
                        self.bv = bv
                    def _get(self):
                        return self.bv[index]
                    def _set(self, value):
                        self.bv[index] = value
                    value = property(_get, _set)
                return GetSet(self.bv)
        return Bits(self)

    def _getslice(self, index):
        if index.step is not None:
            raise ValueError("extended slicing not supported")
        stop, start = index.stop, index.start
        if start <= stop or start < 0 or stop >= self._nbits:
            print "START, STOP", start, stop
            raise ValueError("invalid slice range")
        mask = (1 << (start+1)) - 1
        return (self._value & mask) >> stop

    def _setslice(self, index, value):
        if index.step is not None:
            raise ValueError("extended slicing not supported")
        stop, start = index.stop, index.start
        if start <= stop or start < 0 or stop >= self._nbits:
            print "START, STOP", start, stop
            raise ValueError("invalid slice range")
        mask = (1 << (start+1)) - 1
        mask &= ~((1 << stop) - 1)
        value = value << stop
        if value & ~mask:
            raise ValueError("value out of allowed range")
        v = self._value
        v &= ~mask
        v |= mask & value
        self._value = v

    def __setitem__(self, index, value):
        value = int(value)
        if isinstance(index, slice):
            self._setslice(index, value)
            return
        if not 0 <= index < self._nbits:
            raise IndexError("invalid index")
        mask = 1 << index
        if not 0 <= value <= 1:
            raise ValueError("value must be 0 or 1")
        if value:
            self._value |= mask
        else:
            self._value &= ~mask
-- 
http://mail.python.org/mailman/listinfo/python-list

Reply via email to