Efficient Bit addressing in Python.

Hendrik van Rooyen mail at microcorp.co.za
Sat Oct 11 00:27:44 CEST 2008

 "Tino Wildenhain"  wrote:

> Hendrik van Rooyen wrote:
> > "Tino Wildenhain"  wrote:

> > Sure, one could for instance make a list of eight-entry lists:
> > 
> > io = [[b0,b1,b2,b3,b4,b5,b6,b7],    ]
> what should that represent? Which byte order
> do you have in mind etc?

Each list of bits in the io list would represent bits from least to most
significant, and would have to be collected into one byte before
being output to the hardware in the case of outputs, and would
have their source in one of the bytes read from the hardware, being
scattered from the input byte to the individual bits

> Can you perhaps outline what kind of application
> you have in mind and which operations look meaningfull
> to that?

I am working on a controller for a small machine - I am using
the GPIO port on an eBox to form a slow bus that addresses
latches and buffers on external boards via a ribbon cable.
The idea is that the ebox and the io boards would clip on a 
DIN rail and form a PAC (Programmable Automation Controller)

Each external board has either 8 inputs, or 8 outputs, and the 
addressing scheme allows eight such pairs of boards, so that the 
complete io structure could be represented in 16 bytes - eight
for the inputs, and eight for the outputs, giving 2 arrays of 64 bits,
if I use a real bit to represent the state of the voltage on the wire.

> I'm familar with embedded hardware where you would have
> a couple of registers where you usually only have
> the distinction between 8-bit or 16 bit flag registers
> where it makes sense to individually influence bits.
> Personally I can't follow you on the path to have
> arbitrary lengthy bitfields - even nore to
> have artifically attributes (like bit5) on them.

something like bit5 represents a name for the input or
output in question - in practice, it would have a name
like "e_stop" for an emergency stop input, or "push"
for an actuator that pushes something.

> Just using a big integer to represent your bitfield
> and using binary operators on it does not sound
> so wrong to me in this case.
> Of course one could create a type which derives
> from sequence types and implement something
> like
> bitfieldinstance[bitindex] (where 0 is LSB)
> would you like fries... err slices with that?
> e.g.
>  >>> bf=BitField(10)
>  >>> int(bf[1:])
> 5

If I can just address the thing by name I would be happy:

if e_stop:
   put_everything_off ()

and a simple sequence:

push = 1          # actuates the pneumatic pusher

while not push_forward:   # waits for it to arrive

push = 0         # reverses the motion again.

This of course means that there has to be another
thread active to actually do the i/o on a periodic basis,
gathering the outputs and writing them out, and reading
the inputs and scattering them to the various named input

I would even not mind if I have to write:

if e_stop():



> > This approach has the advantage that you can
> > add a ninth "dirty" bit to indicate that the "byte" 
> > in question needs to be written out.
> What do you mean by "written out" to where?

See above explanation - see also a recent thread here
about "Python string immutability broken" where I posted the
prototype ctypes code, if you are really interested...

> > Is there not some OO way of hiding this
> > bit banging complexity?
> foo & bar is complex? So you want to replace foo + bar
> as well with something? ;)
> > Using getters and setters? - I tend to go "tilt" 
> > like a cheap slot machine when I read that stuff.
> Getters setters? Where would that improve the situation
> beside having to write lots of unneccessary code?

Not necessarily unnecessary - the getters and setters could be
used to actually do the i/o to the relevant card when anything 
makes an access to one of the bits on the memory representation
of that card - that would obviate the necessity for a second thread...

- Hendrik

More information about the Python-list mailing list