# A switch that turns on/off a bunch of other switches?



## UCAudio (Mar 19, 2012)

I have a bunch of UI Switches where each switch turns a group on or off. I want to create a master switch that will turn all of those other switches on or off at the same time to quickly turn the corresponding groups on or off. Havn't had any luck with this yet. Does anyone know of a way to do this?

On a related note, I'm also trying to figure out how to do something similar for a master slider where it controls a bunch of other sliders on the GUI and moves them up or down relative to their current position.


----------



## Big Bob (Mar 19, 2012)

For the first half of your problem, if you declare all the switches in the set contiguously like this:

*declare* switch G1
*declare* switch G2
_{ other switches that are part of the set }_
*declare* switch GX``_{ last switch in set }_
*declare* SID
``SID := get_ui_id(G1)

Then you can turn them all off with a function like this:

*function* all_off(num)
``*declare* n
``*for* n := 0 *to* num - 1
````set_control_par(SID+n,CONTROL_PAR_VALUE,0)
``*end for*
*end function*

Just invoke this function in the ui handler for the master switch, the num parameter would be the number of switches contiguously defined.

For the 2nd half of your problem, why don't you try to see if you can extend this idea 8) 

Rejoice,

Bob


----------



## Raptor4 (Mar 21, 2012)

To my opinion you have to build a setup which uses two behaviors:
1. A Global/Master group switch which turns On/Off all switchers in one go - this is regarding your original ask.
2. It is a good idea to create a counter setup which counts the On/Off status of the switchers which belong to that group, so the Global/Master switch can monitor that status. 
*Example:* Let's say all group switchers are OFF (respectively the Global/Master is OFF too). If you turn ON one of the group switchers then the Global/Master is turned ON automatically showing that the groups is on. You can turn ON the other group buttons - all the time the Global/Master will show (ON status) so if you decide you can turn OFF the Global/Master to kill all at any time. The other scenario is - if you have a few group switchers turned ON and start to turn OFF them one by one till all are OFF then the Global/Master will auto-switch OFF showing OFF status etc. Here is a simple code below:

```
on init
  declare $CounterA 
  declare ui_switch $B_0
  declare ui_switch $B_1
  declare ui_switch $B_2
  declare ui_switch $Group_A
end on
on ui_control ($B_0)
if($B_0=1)
inc($CounterA)
else
dec($CounterA)
end if
if($CounterA>0)
$Group_A :=1
else
$Group_A :=0
end if
end on
on ui_control ($B_1)
if($B_1=1)
inc($CounterA)
else
dec($CounterA)
end if
if($CounterA>0)
$Group_A :=1
else
$Group_A :=0
end if
end on
on ui_control ($B_2)
if($B_2=1)
inc($CounterA)
else
dec($CounterA)
end if
if($CounterA>0)
$Group_A :=1
else
$Group_A :=0
end if
end on
on ui_control ($Group_A)
$B_0 :=$Group_A
$B_1 :=$Group_A
$B_2 :=$Group_A
if($Group_A=1)
$CounterA :=3
else
$CounterA :=0
end if
end on
```

Regards,

R4


----------



## Big Bob (Mar 21, 2012)

Hey Raptor4,

Nice illustration of a master/slave switch configuration.

I don't know how many you might be interested in a little coding trick that can often be used to eliminate a lot of if-else clauses. Consider the following which incidentally should work identically with the prior if-else version.

*on init* 
``*declare* $CounterA 
``*declare* ui_switch $B_0 
``*declare* ui_switch $B_1 
``*declare* ui_switch $B_2 
``*declare* ui_switch $Group_A 
*end on*

*on ui_control* ($B_0) 
``$CounterA := $CounterA + 2*$B_0 - 1
``$Group_A := sh_right($CounterA-1,31)+1
*end on*

*on ui_control* ($B_1) 
``$CounterA := $CounterA + 2*$B_1 - 1
``$Group_A := sh_right($CounterA-1,31)+1
*end on* 

*on ui_control* ($B_2) 
``$CounterA := $CounterA + 2*$B_2 - 1
``$Group_A := sh_right($CounterA-1,31)+1
*end on* 

*on ui_control* ($Group_A) 
$B_0 :=$Group_A 
$B_1 :=$Group_A 
$B_2 :=$Group_A 
$CounterA := $Group_A*3
*end on*



Generally, the KSP is much more efficient with evaluating expressions than in making conditional branches, so the above version is not only much more compact in terms of lines of code, but, it is also likely to use less cpu to execute.

Of course the if-else version is perhaps much easier to understand without any further explanation. However, if anyone is interested in using the above technique, I'll be glad to explain the general idea behind it.

Rejoice,

Bob


----------



## Raptor4 (Mar 21, 2012)

> However, if anyone is interested in using the above technique, I'll be glad to explain the general idea behind it.


Hi Bob,
It is a honey for me - I expected your optimization (as a KSP beginner I knew that there must be some optimized way). I'm coming from the Logic Pro environment and I'm a great fan (and developer) of hi-tech optimized enviro schemes... I'll add your example to my notes and re-think it in details.
Thanks again !
By the way what is "sh_right" ? I have not see that before...

Regards


----------



## Big Bob (Mar 21, 2012)

> By the way what is "sh_right" ? I have not see that before...



The instruction *sh_right(V,n)*, shifts the bits in the value V to the right by n bit positions. There are two types of right shifting -- logical and arithmetic. With a logical right shift, zeros are always shifted in on the left while, with an arithmetic right shift, the sign bit is shifted in on the left. The KSP only has an arithmetic right shift (no logical). So, for V < 0, ones will be shifted in on the left while for V >= 0, zeros will be shifted in on the left.

Therefore, the expression *sh_right(V,31) *can be used as a conditional predicate of sorts. If V < 0, sh_right(V,31) = -1 whereas if V >= 0, sh_right(V,31) = 0. If you want the more traditional boolean predicate you can simply add one, making it *sh_right(V,31)+1*. For this expression, any positive value will evaluate to 1 whereas any negative value will evaluate to 0.

Rejoice,

Bob


----------



## polypx (Mar 21, 2012)

Hmmm -- I still don't understand. Does that mean you have to imagine a number as a sequence of bits? And what is a bit anyway?


----------



## mk282 (Mar 22, 2012)

Yeah, you have to think binary for those. Easy test:


```
on init
	declare $i := 1

	message($i & " | " & sh_left($i,0))
end on
```

Change the number in sh_left, and you will see an increasing series: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, etc. This is going exactly through the digit weights of a binary number.

sh_right does the opposite. Set $i to 1024, change sh_left to sh_right, and change the numbers from 0 incrementally. You will get 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 0.


----------



## Raptor4 (Mar 22, 2012)

Hi Bob,
Thanks for the detailed "sh_right" explanation - it make sense. Now I remember something about the "Bit Operators" described in the old K2 manual. 
Originally I was confused why you use n=31, I think n=0 or n=1 etc will work as well in our scenario. 
Here is another simple optimization without using "sh_right" for the $Group_A strings:

```
$Group_A := $CounterA-1+1
```
And yes I understand the "sh_right" big advantage :wink: 



> Does that mean you have to imagine a number as a sequence of bits? And what is a bit anyway?


Here is someinfo about.


----------



## Big Bob (Mar 22, 2012)

Yes you may be able to 'get by' with something like

```
$Group_A := $CounterA-1+1
```
 but only because setting a control to anything other than zero turns it on. I tried to illustrate with a predicate that evaluated only to zero or 1 (not zero or non-zero).

sh_right something other than 31 would suffer from the same kind of problem. Generally, you will want your conditional predicates to evaluate to only two values. But for any specific situaton, anything that works will do the job :lol: 

The main idea, which you seem to have picked up on is that you want to use conditional expressions that help you avoid branching with if-else.

Rejoice,

Bob


----------



## Big Bob (Mar 22, 2012)

polypx @ Wed Mar 21 said:


> Hmmm -- I still don't understand. Does that mean you have to imagine a number as a sequence of bits? And what is a bit anyway?



Hi Dan,

Did the other reponses sufficienly answer your questions? If not, please let me know, I don't want to belabor the point.

Rejoice,

Bob


----------



## polypx (Mar 22, 2012)

I think I've got it... but it's a strange way to think. 

I understand MK's example clearly, but hmmm... 

Are you just using it to increment a switch? A bit like x := (x+1) mod 2 ?


----------



## Big Bob (Mar 22, 2012)

Hi Dan,



> I think I've got it... but it's a strange way to think.



Yes I suppose so, but, not for us old bit twiddlers :lol: 

Let's see if this helps or hurts.

In the decimal system, when we write a number like 345, the position of the digits are important. ie we give the digits to the left a bigger weight than the digits to the right. Each position to the left is the next power of ten higher than the previous one. So, 345 really means 3*10^2 + 4*10^1 + 5*10^0 = 3*100 + 4*10 + 5*1 = 300 + 40 + 5.

When the number base is 2 (ie the binary system), there are only two digits (0 and 1) but we still use the positional weighting of the bits (BTW 'bit' is a contraction of binary digit). So, when we write 111 in binary, it means 1*2^2 + 1*2^1 + 1*2^0 = 4 + 2 + 1 = 7 in decimal notation.

K4 integers contain 32 bits and from right to left the bit positions are numbered 0 to 31. The most significant bit (MSB) is thus bit 31 and K4 uses that as the sign bit. If bit 31 is on, it means the number is a negative value. So instead of giving the sign bit the value 2*31 as would be the case for unsigned numbers, the sign bit is actually given the value -2^31. This strategy is known as two's complement representation. 

Everytime you shift an integer to the left by one bit position, it essentially moves all the digit weights up by one position to the left which is a factor of 2 in binary. Its like adding a zero to the right of a decimal number (which multiplies all the digit weights by 10).

To properly handle negative numbers (ie those where the sign bit = 1), right shifts must shift in ones on the left. Whereas, positive numbers shifted right have to have zeros shifted in on the left. This is usually given a name like sign extension.

Normally, you can usually get by with just the division and mod operators but there are situations in which the shifting operations can be very useful.

Conditional predicates are just one kind of usage that can benefit from using the sh_right operator. When you shift *any* positive number to the right by 31 bits, all significant bits are thrown away so you end up with 0. On the other hand, when you shift *any* negative number to the right by 31 bits, you end up with all ones (because of sign-bit extension). When all the bits of a 32-bit integer are ones, the value in 2's complement will be interpreted as minus one. Therefore, *sh_right(V,31) *+ 1 has only two values, either 0 or 1 (no matter what value V has). All V < 0 results in a zero value and all V >=0 results in 1. This kind of expression is often called a conditional predicate or verb and such expressions are very useful in reducing the number of branches in your code.

Keep in mind that it's not really necessary to know why or how these conditional predicates yield their two-state outputs to benefit from them. All you need do is keep a list of these things handy (as long as they emanate from a reliable source that is). :lol: 

Rejoice,

Bob


----------



## polypx (Mar 23, 2012)

A very reliable source indeed! I think I've got it, and I can see how that could potentially be useful to turn any negative number into a 0 and any 0 or positive number into a 1.

I'll store this for future reference. I do understand what binary is, in theory, but shifting bits around is not my first port of call when approaching a problem. It's good to see an example of how it can be useful, and I'm sure there are many things you can do this way if you're comfortable with it.

Thanks Bob, you keep on teaching me here, and it's deeply appreciated.

cheers, Dan


----------



## UCAudio (Mar 24, 2012)

Just wanted to log in and say thank you Bob and everyone else who contributed to this. I'm going to try to really dig in and apply all of this tomorrow. Crazy how much less KSP time I have now that I have a baby to look after! Anyway, thanks again guys!


----------

