Lean solution for radio-button like behaviour

edmunds

Senior Member
Dear all,

While working on the OLED project, I'm implementing a radio-button-like feature - the user should be able to select ONE out of a number of options. In practical terms, this means if one value of an array is set, all others should be cleared. While there are three options to choose from, one can get away with something like the case statement matrix below. If you have 10 options, however, this alone will take 25% of your program memory :).

Code:
      UpdateBit:
        Symbol TLMode = b17
        Symbol BitNumber = b18

 	togglebit TLMode, BitNumber
  	Select case BitNumber
  	case 0 : Clearbit TLMode, 1 : Clearbit TLMode, 2
  	case 1 : Clearbit TLMode, 0 : Clearbit TLMode, 2
  	case 2 : Clearbit TLMode, 0 : Clearbit TLMode, 1
        endselect
      return
Is there a better way?

Thank you all for your time,

Edmunds
 

edmunds

Senior Member
As it happens, I came up with a solution shortly before posting :). I think it actually makes sense, since to write a decent question, you need to structure your problem. And it is not difficult to solve a well structured problem. The difficulty is structuring it in the first place. Better solutions are welcome, of course.

Code:
UpdateLaneStateBit:
  Select case MenuPage
  case 19
    for Counter = 0 to 7
    	if TLMode bit Counter set then
  	  	if Counter = BitNumber then return
  	  	endif
  	  	goto ResetTLMode
  	  endif
  	next Counter
ResetTLMode:
  	TLMode = 0
  	setbit TLMode, BitNumber
  	write 16, TLMode
  endselect
  gosub ShowBitState
return
Edmunds
 

edmunds

Senior Member
Don't you just love it when Hippy comes up with a zinger like that? :)
I do love it. And I will love it even more, when I understand it :).

Dear @hippy,

Sorry, I have been learning about bit shifting since late last night, but I don't get your suggestion.

Let's say TLMode is storing 8 options, one bit for every option. I understand how your suggestion would work if the BitNumber always selects the next bit i.e.

TLMode = %00000010 << 3 = %000100000.

But what happens, when TLMode = %00010000 and BitNumber (the selected option) is 0? If I understand this bit shifting thing correctly, then

TLMode = %00010000 << 0 = %00010000. Not good. Should be %00000000 now.


Thank your your time,

Edmunds
 

hippy

Technical Support
Staff member
EDIT: Just realised I have a misinterpretation of your code ... see next post

Note that "TLMode = 1 << BitNumber" doesn't use the existing value of TLMode, only shifts the value 1 left BitNumber times -

0 = %00000001
1 = %00000010
2 = %00000100
:
6 = %01000000
7 = %10000000

For other cases, it depends on exactly what you want or need. My example allows any of 8 bits to be set, such that one and only one bit is set at a time, set by BitNumber 0 through 7.

If you desired 0 to clear all bits, 1 to 8 to set one of the 8 bits you would need something slightly more complicated ...

Code:
If BitNumber = 0 Then
  TLMode = 0 
Else
  BitNumber = BitNumber - 1
  TLMode = 1 << BitNumber 
End If
But, if you use BitNumber of 0 to 7 to set a bit, and 8 to clear all bits you can still use -

TLMode = 1 << BitNumber

1 shifted left 8 times would be $0100 and only the lower 8-bits would be stored in TLMode.
 

hippy

Technical Support
Staff member
Sorry, just realised your code doesn't just set the bit, it toggles the bit and clears all others. That's a bit more complicated ...

BitMask = 1 << BitNumber
TLMode = TLMode And BitMask Xor BitMask

Or, and if you want to avoid that extra BitMask variable ...

TLMode = 1 << BitNumber And TLMode
TLMode = 1 << BitNumber Xor TLMode
 

edmunds

Senior Member
Sorry, just realised your code doesn't just set the bit, it toggles the bit and clears all others. That's a bit more complicated ...

BitMask = 1 << BitNumber
TLMode = TLMode And BitMask Xor BitMask

Or, and if you want to avoid that extra BitMask variable ...

TLMode = 1 << BitNumber And TLMode
TLMode = 1 << BitNumber Xor TLMode

Ok, thank you, a few days worth of studying, I guess :D. I'll be back if I fail to understand this.

Edmunds
 

edmunds

Senior Member
TLMode = 1 << BitNumber And TLMode
TLMode = 1 << BitNumber Xor TLMode
First - it works!
Second - I now understand what is going on, but coming up with something like this to solve a problem I proposed will obviously take some practice. :)


Cheers,

Edmunds
 

westaust55

Moderator
Will this provide a useful solution:
TLMode DCD bitnumber
There will always be 1 and only 1 bit set corresponding to bitnumber.
That will handle up to 16 bits in a word variable.

so try this (untested):

TOGGLEBIT TLMode, BitNumber
TLMode DCD bitNumber AND TLMode


Note that both << and DCD are only available on the X1 and X2 parts.
 
Last edited:

Circuit

Senior Member
Will this provide a useful solution:
TLMode DCD bitnumber
There will always be 1 and only 1 bit set corresponding to bitnumber.
That will handle up to 16 bits in a word variable.

so try this (untested):

TOGGLEBIT TLMode, BitNumber
TLMode DCD bitNumber AND TLMode


Note that both << and DCD are only available on the X1 and X2 parts.
This is turning out to be quite a day for learning more and more about PICAXE; I had not become aware of DCD before. For others who share my ignorance, it is mentioned here; http://www.picaxe.com/BASIC-Commands/Variables/let/ but there is only a rudimentary definition. Westy, could you possibly provide a short (or enlighteningly elaborate if you have the time...) explanation of what this is all about?
 

westaust55

Moderator
DCD is simply a calculation of 2 to the power of n (2^n)

Think of the bits in a byte or word variable ands its value:

Code:
Bit      7  6  5  4  3  2  1  0
Value  128 64 32 16 08 04 02 01
The value in each case is calculated by the formula:
Value = 2^bitnumber

Which in PICAXE BASIC equates to
Value = DCD bitnumber

The advantage is that DCD is not only setting the desired bit,
but also clearing all the other bits in the byte/word variable.

Trust that helps
 
Last edited:

Circuit

Senior Member
Westy, thank you; that is an explanation of great clarity. This is clearly a very useful function and now that I understand your explanation of it, I will be using DCD and NCD in future programs. I would suggest that your concise explanation could be incorporated into the text in the Basic Commands guide to great effect.

Edmunds, thank you. A most useful cross-reference site that helps fill in some of the areas where the information at PICAXE is absent.
 
Top