Bit array

BeanieBots

Moderator
I'm after a neat solution to setting/resetting individual bits as part of an array.

The array will be 42*48 bits but the 48 can convieniently be broken down into 3 bytes.

For example:
b2 holds a RAM location
b3 holds the bit to be set

So if b2=4 and b3=6, is there a way I could set bit 6 of SFR RAM location 4 without resorting to a large if/then, select/case/ or branch arrangement.
 

hippy

Ex-Staff (retired)
Which PICAXE are you using ?

This uses a 28X2 and b20 onwards as a bit array, sets bit 4 of the 4th byte of the array ( index 3, that is b23 ) ...

#Picaxe 28X2

SerTxd(#b20," ",#b21," ",#b22," ",#b23,CR,LF)
b2=3 : b3=4 : Gosub SetBit
SerTxd(#b20," ",#b21," ",#b22," ",#b23,CR,LF)
End

SetBit:
bptr = b2 + 20
@bptr = 1 << b3 | @bptr
Return

Similar can be used with other PICAXE's.
 

QuIcK

Senior Member
I dont understand how 48bits can be broken down to 3 bytes. do you mean 6 bytes?
do a loop to reduce it down to byte and bit refrences:
Code:
do until b3 < 8
b3 = b3 - 8 'will point to which bit
inc b4 'will point to which byte
loop
this may be able to be reduced to:
Code:
b3 = b3/8 'whole number, may need a +/-1
b4 = b4 // 8 'remainder, ie which bit
so now we know which byte, and which bit.
Code:
get b3, b5
b5 is now the byte we are working on
b4 is the bit we are to toggle
Code:
'to switch bit on, use
b6 = dcd b4 'turns 4 into %00001000
b5 = b5 OR b6 'means that bit 4 will be a 1 due to mask
'to switch bit off use
b6 = dcd b4 'turns 4 into %00001000
b6 = NOT b6 'turns previous 4 into %111101111
b5 = b5 AND b6 'AND will make bit4 0 due to mask.
'to toggle use
b6 = dcd b4 'turns 4 into %00001000
b5 = b5 XOR b6 'means that bit4 will be the oppsoite of what it was.
'if it was a 1: 1^1 = 0 (exclusive or), if it was 0: 0 ^ 1 = 1
as hippy has shown, tho, using the bitpointer might be easier
 
Last edited:

BeanieBots

Moderator
Thanks Hippy, just the sort of compact code I was after.
It is indeed for a 28X2. (should have specified).
I was missing the ">>" operator.
Don't think I can spare that many b# variables for the array but I'm confident I can modify your code to work with either RAM or the scratchpad.

@QuIcK,
Thanks for putting in the effort but I think a select case or branch would be just as compact as your offering and easier to follow.

You're quite right.
48bits = 3*16 = 3 words = 6 bytes.
Fortunately it's already broken down into byte (actually word, hence my own confusion) values (whilst it's created) so that part is already done.
It was the bit(N)=X that elluded me.

EDIT:
Thanks for the pointer to "DCD". That would be another option and might even be more appropriate depending which way I structure it.
 
Last edited:

BeanieBots

Moderator
Having now implemented Hippy's masterpiece, I now have the reverse problem.
How to get the data back.
Anyone got a comparable code snippet which can do something along the lines of:-

b0=byte(X),bit(Y)

EDIT:
Think I might have solved this but would like a sanity check.

bptr = X
b0=1 << Y AND @bptr
 
Last edited:

BeanieBots

Moderator
Just as you think you've cracked it, somebody does it better!

Wait till you see the finished 'product'.
You'll have such a laugh:eek:

It's so nice to have a 28X2 that has space to let you write sloppy code:)
 

BeanieBots

Moderator
OK, let's go for the full suite.:)

Toggle bit is simple enough:-

ToggleBit:
bptr = Y
@bptr = 1 << X XOR @bptr
Return

But I'm struggling with UnSetbit.
The best I could come up with is this:-

UnSetBit:
bptr = Y
@bptr=not @bptr
@bptr = 1 << X OR @bptr
@bptr = not @bptr
Return

I'm sure that can made a lot neater. I just can't see it for looking.
 

Technical

Technical Support
Staff member
Needs another var but

UnSetBit:
bptr = Y
mask = 1 << X
@bptr = not mask AND @bptr
Return

or if you dont mind corrupting X

UnSetBit:
bptr = Y
X = 1 << X
@bptr = not X AND @bptr
Return
 
Last edited:

BeanieBots

Moderator
The coordinates can be sacrificed, so option 2 looks the best bet.
Thanks.

I'll tidy this lot up at some point and publish in the 'snippets' section as I think they could be very useful little routines.
 

hippy

Ex-Staff (retired)
Or ...

UnSetBit:
bptr = Y
@bptr = 1 << X XOR $FF AND @bptr
Return

The "1 << X" can be changed to "DCD X" in all the examples.

I really think we should have a thread to determine exactly how many ways there are to skin a cat and which is the most optimal :)
 

Technical

Technical Support
Staff member
"DCD X" uses less code space (because there is less data involved) and hence will also run (marginally) faster.
 

hippy

Ex-Staff (retired)
I was gettng intrigued as to what you were doing.

BTW, "DCD X" was about 10% faster than "1 << X" when I timed it. No exhaustive testing but that's the ballpark.
 

BeanieBots

Moderator
Thanks again for your input on this.
As you know, software logic is not my strongest point.
Please have a look at the code which I have now published.

The PICAXE 'player' can take up to 7 seconds to make it's mind up and that's with only a single depth search. A second level would take that to around 1 minute.

Anyway, the bit manipulation is all done and works well.
I'm sure others will find these routines useful for something.
 
Top