Analogue Logic 1 - Fundamentals
by, 10-05-2010 at 08:11 PM (7703 Views)
Ana.logue Signal Processing
Binary's for n00bs foo'!!!
Part 1 - Concepts and Fundamentals
I’ve decided to kick off Logic Blog 2.0 with our first steps into the world of analogue (or ana.logue in-game because yes, sensible words are still filtered in LBP2, *sigh*) logic. Analogue signal processing is the non-obvious side of LBP2 logic and whilst most creators with some experience with LBP1 logic are going to be comfortable with the digital side of things (basic AND, OR operations, switching things on and off, etc), the analogue system is liable to pass many people by as it’s largely hidden from the user. It’s also very, very powerful.
In LBP1 we didn’t really have that much use for analogue signal manipulation and the tools that were available weren’t very suited to the jobs of producing analogue signals or doing anything much interesting with them, we mostly stuck to boolean operations, except for basic things like gradually increasing the speed of a bolt and very occasionally something a little more complex.
However, now we have movers and rotators and hologram etc., that respond very well to analogue controls for quite subtle effects and also we have processing devices that allow us to do some very interesting operations on these signals and opens up a wide range of tuning and refinement that would be impossible, or at least prohibitively complex, with digital systems. Analogue processing is also where you will find some very subtle effects beyond the boring TRUE / FALSE of digital processing.*
1. Introductions to Analogue Signals
We'll begin with an overview of analogue signals in LBP and some terminology definitions:
1.1. Representations of Analogue Signals in LBP2.
For the sake of the logic blog (and probably in general around the forums), you will likely see me referring to the values of analogue signals in LBP2 in the same terms as they are on he battery device: an signed integer between -100% and +100%, though I’ll often miss of the percent signs, because I’m lazy. In actual fact, I’ve found that analogue signals do (or at least can) have a much finer granularity than that. I can successfully differentiate between 99.93% and 100% - and I believe that the actual game granularity is finer still. I'm not sure how much use this would be, though awareness of this fact may be useful for bug fixing.
Spoiler - geekNotes: On Analogue / Digital DualityIn LBP1 we had a number of signal types and each device that output a signal was capable of outputting one of these signal types. I’d guess most of my readers, even those not in the beta, understand that in LBP2, this has been changed. Now each device outputs a signal to the wire, and that signal is interpreted as one of many things - several devices as consumers on the wire may all interpret it as a different signal type.
The way in which this is achieved, when you break down the engine, is that ever device actually outputs 2 signal types simultaneously (along with possibly some extra data - I'll get back to you on that) which we shall call the "analogue" and "digital" components of the signal. Each of the signal types you see in tweak menus is merely an interpretation of one of these, eg. “speed”, “strength” and “brightness” are interpretations of the analogue component, whilst "directional", "on/off" and "one-shot" are interpretations of the digital component.
What tends to happen, is that the way individual devices produce and process the analogue and digital components means that if you design a system for analogue processing, the chances are your digital signals will mean nothing and vice versa. They are two wholly different animals and ne’er the twain shall meet… Except when we force them to, of course – but conversion techniques are a topic for another day.
Also, technically these “analogue” signals aren’t truly analogue, but then again the “digital” signals aren’t truly digital either, so I think we can be consistent in our inaccuracy for the sake of not being too pernickety, yes? Good, moving on....
1.2. Notes on Negativity
In addition, when dealing with negative values (which we will touch on here, but not in great depth) some switches will not cope with negative values in the way you might expect. Typically this involves taking the magnitude of the value only. That is to say that -55% is considered to be the same thing as +55%, when only considering magnitude. Which, obviously, it isn’t and this fact can cause some problems if you aren’t expecting it – especially when you need to keep track of which devices only deal with magnitude and which use the signed value. And to make matters worse, some devices swap between which values they use, depending on how you’ve tweaked them
1.3. Notes on Inversion
Pretty much every device that has an output in this game can have that output inverted (or NOTted if you like). For the most part, an inverted signal will be 100 – s, where s is the normal, uninverted value. This of course makes no sense with negative values of s, as the result would be out of range. It appears that the LBP way to get around it is to treat all analogue values as magnitude, before inversion, so:
To avoid confusion, I’ll be using the terms “Negative” and “negation” to refer to changing a value from positive to negative and vice versa, and the term “inverse” and “inversion” to refer to this characteristic of the NOT function in LBP.Code:s | inverted s -------------------- 0 | 100 100 | 0 35 | 65 -35 | 65 -70 | 30
Of course nothing is that simple, there is one exception to this rule. The Combiner device, when set to invert output actually gives the negated value (magnitude equal, but sign changed). Therefore an inverted output on a combiner is not the same as running the output through a NOT gate. It's the same as swapping around the inputs, so one really wonders if this is a bug or not (it has been reported).
2. Analogue Signal Sources
This section covers analogue signal sources, which for the most part are very simple, other than the tag and player sensors, which are surprisingly complex. These signal sources will be the initial inputs to your analogue processing system as they don’t have any explicit inputs themselves. Though many of them are sensors that that arguably should be considered to have an input – what I mean is that there is no wire coming in.
2.1. Grab, Impact Water and Sticker Sensors
There is no real sense in having an analogue outputs for these (except maybe water – indicating depth – but then that’s tricky to quantify into a percentage). So they output 100% if the particular conditions of the switch are met, and 0% if they are not.
Batteries will always output the value you set them to, which is an integer between -100% to +100%. This may seem a little pointless, but in analogue signal processing it can often be useful to define offsets and thresholds that are fixed in the system – batteries provide this and they are give convenient system tuning.
2.3. Score and Projectile Sensors and the paintswitch.
The analogue output for these devices can be described as the percentage complete they are. So for the score sensor, the analogue output is:
(target score – current score) / target score
2.4. Player Sensors
Much like when you used to use the sensor switches with speed output in LBP1, the value of the signal from a player sensor is greater the closer the player is to the sensor. It’s quite hard to quantify, as placing sackboy accurately is basically impossible, but it seems that the relationship is roughly linear, except for the fact that there is a smallish area close to the switch that will always give 100%, meaning that you don’t have to be slap bang on top of the sensor for it to read 100%. Of course if the angle is smaller 360 then you will read zero if outside that angle. However, that’s not the whole story, as the player sensor now has a couple of new tweaks, both of which give interesting results if you analyse the analogue outputs.
Firstly, the minimum range tweak, which gives you a dead zone in the centre of the detection area. It should be clear that if you are in the dead zone then the signal output will be 0. However, on the edge of the dead zone, the analogue signal outputs 100%, so the scale is modified to accommodate for this. In addition, you also lose the 100% zone on the sensor if your minimum radius is greater than zero. As this is a bit confusing, I made a graph to demonstrate both the effects of the 100% zone and the size of the deadzone on the signal value:
fig 2.4.1. The Effect of Minimum Radius on Player Sensor Outputs
Secondly, there is the new “Number of Players Required” tweak. Obviously, if you don’t have the correct number of players in the sensor area, then output is zero, however, if you do have the right number of players (or more), it bases the value on the distance of the nth player. So if you select “require 2” on the sensor, it will tell you the distance to the second closest sackboy. Which is nice.
2.5. Tag Sensors
These work in almost the same way as the player sensors do, with 100% zones and dead zones, with detection of the nth closest matching tag (remembering that tag labels exist, so if labels do not match, neither do the tags). The tag sensor also has one other useful tweak, Output Value. The default, “closeness” will output a value similar to the graph in fig 2.4.1., whereas “signal strength” will output the value of the signal that is input to the tag - including the sign.
This means that it is possible to wirelessly transmit analogue values in the full range (+/- 100%) by simply using a tag and sensor. which is quite a significant feature when you remember that emitted objects cannot be wired to anything that is not emitted with them.
Apologies for the misinformation in the original text, it seems I didn't do my research well enough on this particular aspect. Thanks to Rogar for pointing out my failures. What can I say, I am only human, despite what you may have heard rumoured....
3. Analogue Signal Processing
Following on from analogue signal sources are the devices that are used to do the processing. Some of these aren't actually analogue processors, as they can't utilise analogue inputs and I suppose if used in an analogue system they are sources, but I've split it this way because it seemed like a good idea at the time and renumbering sections is a pain. Deal with it.
3.1.Toggles, Randomisers and Select Switches
These have no concept of analogue input and will only respond to the digital aspect of the input signal(s). The outputs do have an analogue component, however this will take a value at 0% or 100%, nothing in between.
The counter, like the devices above, doesn’t have an concept of analogue inputs, however, as with the projectile sensors etc. its analogue output is the ratio of maximum value to current value. This makes the counter (amongst other things) a very useful tool for debugging analogue signal processors – much like the battery allows easy tuning through tweak settings, the counter allows quick modification of test data from a Controlinator test harness (I am now almost exclusively using Controlinators for component - level testing in LBP2). It's also quite useful if you wish to adjust offsets and thresholds to modify your system at runtime - for example, to modify difficulty automatically each time the player fails, or to increase difficulty as you go up a level.
3.3. ANDs ORs XORs and NOTs
These are our basic digital processing components, but they also have analogue processing abilities that are likely to be rather unexpected. The NOT simply passes the signal through, inverting it if required (remembering the inability to invert negatives above), but the others have some interesting properties when you look at the analogue component of their outputs.
The AND gate is effectively a min() function - it’s output is equal to the smallest value input. So for signals of 10, 63 and 42, the output would be 10. To compliment this, the OR gate is a max() function, so the output value from the same three signals would be 63. Note that these definitions make sense in terms of using binary (0 / 1) inputs for the same gates, which is probably why this happened.
Spoiler - geekNotes: on Handling of Negative ValuesOne interesting point about the AND and OR circuits is that they carry out this min() or max() function on the magnitude of the inputs, but will pass through the exact value of the input:
Note that in several cases, the output for max() is smaller that the output for min(), which is conceptually strange but does actually make sense, in a roundabout way. If you go back to the original definitions as ANDs and ORs. Check out the bottom line for evidence. If doing a true min(), then the AND would come out as having a non-zero value, even when one of the inputs is set to zero.Code:Inputs | AND / | OR / a | b | min() | max() ------------------------------------ 100 | 35 | 35 | 100 50 | 65 | 50 | 65 50 | -10 | -10 | 50 -50 | 30 | 30 | -50 -45 | -60 | -45 | -60 0 | 100 | 0 | 100 0 | -100 | 0 | -100
Or... something, I don’t actually know what the rationale is for this behaviour, but that’s the way it is – learn it, it’ll stop you hitting problems later on
The XOR is a strange beast and seems to do something along the lines of a max() function on the analogue inputs, but then combines this with it’s binary output. Which means that to understand the complete behaviour you have to keep track of both analogue and digital inputs, which as described in the geekNotes above, and as we will find out at a later date when we dig deeper into the duality of signals, are generally divergent if any processing has been carried out on them. I’m sure we can utilise this to our advantage at some point but for now I’m struggling to find genuine uses and I don’t like it, so we shall move swiftly onto something I do like:
3.4. Combiners and Splitters
The Combiner works out as a simple subtraction device and output is equal to the difference between the two inputs. It’s definitely worth noting that the inputs on these are taken to be magnitude only so you can’t use negative numbers within a subtraction and achieve the correct arithmetic result. The output can be negative and will be arithmetically correct, assuming that both inputs are positive. This might be a bit confusing, so here are some examples:
When including negative values in the subtraction, as either operand, the result is incorrect. 50 – (-10) should give 60, however the actual calculation performed is 50 – 10, to give 40.Code:Inputs | Correct | Combiner + | _ | Answer | Output ------------------------------------ 100 | 35 | 65 | 65 50 | 65 | -15 | -15 50 | -10 | 60 | 40 -50 | 30 | -80 | 20
The splitter is pretty simple – if the input is negative it outputs the magnitude of the signal through the negative output, if the signal is positive then it outputs the magnitude through the positive output. In both cases the signal output is a positive value. Splitting signals is very useful given the caveats associated with manipulating negative values and can also be used for simple things like checking "is this signal positive or negative?".
If any device is the king of analogue processing, it’s the timer. Simple enough to just trigger an event every few seconds, yet powerful enough to be used at the core of a data storage device or even integration (yes, LBP2 has calculus) of analogue signals against time and a whole bunch of stuff in between. It can also be quite neatly geared up as a signal source, to produce periodic waveforms (natively triangle and sawtooth, but with a couple of bits of extra logic, square waves, trapezoids and possibly sine and cosine – though I’ve not quite got as far as achieving true sine and cosine yet, but I think I know how).
The output of the timer is, much like some of the other tools, the ratio of max value to current value. However, in addition to binary inputs (of which there are a few nice things such as “start counting up / down” and “forwards / backwards”) the timer also has a speed setting, which is fantastic. Basically, if you put a 50% analogue signal into a timer with speed inputs, then the timer will fill up half as fast as normal, change it to 25% and the rate of change halves again, drop it to 0% and it stops. But this also works for negative values as well, and a negative input will reduce the value of the timer, at a rate proportional to the input value.
I’m not actually going to go into the usage of sequencers here, I'll save that for a later date, as they has a very specific and unique role in the world of analogue signal processing, when we get around to turning it from a technical curiosity into a powerful decision-making tool.
4. A "Simple" Example
So far, all we've done is look at the basic tools and their functions and it doesn't seem like much could be done with them - really we've only got a few sensors to detect the state of the world, and a few basic operations we can carry out and that's all there is to our analogue toolset... But when you think about it, this is actually more functionality than the individual components we used to use for logic in the old game and look what we achieved with that.
Next instalment I'll actually put together a couple of neat microchips that will allow us to expand this toolset with more functions, but as this is a bit long and technical so far, I don't want to do any in-depth examples, so I'll finish off with a simple waveform manipulation circuit I dreamt up, which is shown below (click for higher res):
fig 4.0.1. Wavform Filtering Circuit
4.1. Signal sources
In this case, we're using the timer (labelled 1 in fig 4.0.1) and some batteries (2, 4, 6) as the signal sources. The timer is configured with the following settings:
Target Time: 2s (note, this is arbitrary)
Input Action: Forwards / Backwards
Invert Output: Yes
This set-up will produce a triangle wave, as looping the inverted output back to the forwards/backwards input causes the timer to fill up linearly, then empty linearly, then repeat. I don't want to go too much into exactly why this is, but that is what it does, as per the graph below:
fig 4.1.1. Triangle Wave (System Input)
Note that the period of the signal is twice the Target Time setting (as the timer must fill up for 2 seconds and then empty for 2 seconds).
4.2. Signal Limiting
As discussed above, some of the simplest operations we can do on analogue signals is min() and max(), using ANDs and ORs. We can use this to achieve some boundary limiting on the signal, preventing the signal going above 80% or below 20%.
So taking the output of the timer and using an OR gate (labelled 3) with a battery (2) set to output constant 20% will give us a max function, which leads to a lower boundary. To clarify: if the timer output is greater than 20, the output of the OR gate is equal to the timer, but if the timer drops below 20, then the OR gate will output 20.
After this we do the same thing with an AND gate (5) to do a min() with an 80% battery (4), to give an upper limit, and the resulting output of the AND gate is shown below (with the original wave in dotted lines). You can see that the timer's output is ignored when it exceeds the minimum and maximum bounds that we have set for it:
fig 4.2.1. Trapezoid Waveform (triangle with boundary limiting)
Conceptually it is a little confusing that we use a min() function to create a maximum value, but that is the way of the world, I'm afraid - it's certainly not my fault!
4.3. Removing the DC Offset
Sometimes, especially with waveforms, it's useful to have them centred around 0, and to do this we need to shift the whole wave down by 50 (the point at which it is currently centred - its average value). This is a simple subtraction operation using a combiner (7) and a battery set to 50% (6) and results are as shown:
fig 4.3.1. Trapezoid Waveform with DC component removed
4.6. Extending the concept
The advantage of centring the signal around zero is that over time, the value averages to zero - if you were to put that signal into a mover, it would move forwards a bit, then backwards a bit, then repeat, but it wouldn't drift from its original location. The same is true if you put the signal into a timer with speed input.
The timer with speed input actually works out as being an integration of the input signal against time. I'm not going to explain why - those of you with enough calculus to understand why can probably work it out on your own. One reason integration is good is that it can quite often give us curvy waveforms, and curvy is nice, for all manner of reasons
Integrating our trapezoidal waveform (fig 4.3.1) actually turns out to be a rough approximation of a sine wave, as shown below:
fig 4.3.1. Trapezoid Waveform Integrated to Approximate Sine
Note: This is only an approximation of a sine wave, I think it's possible to produce completely accurate sine and cosine signals, in the range -100% to 100%, but I haven't tried out that mechanism yet as it's a weird complex loopback system, that makes my head hurt to think about it.
To achieve this result I have actually fed the signal into timer starting at 50% and then deducted 50% from the output value, to recentre the signal around zero. This is shown below as an extension of the original image (components 8 and 9 provide this extra processing - the 50% battery at 6 is reused as shown):
fig 4.4.1. Extended Waveform Filtering Circuit
Spoiler - geekNotes: More on Analogue / Digital Duality
Remember how I said to you that if you create a system for analogue processing, then the digital output will be garbage? Well this circuit is a perfect case example of that. In the analogue component in both of these circuits, we have this waveform shifting from positive to negative values over time and on the Digital output for the first one, we have.... 0. Always 0. It never changes. IN the second circuit, the digital output is fixed at -1 (yes, digital values can have negatives, hence why calling them "digital" is a lie) and this two never changes.
Just thought I'd bring that little fact up - don't expect your binary outputs of analogue systems to make any sense.
Also, when designing analogue systems, the wires are not your friend. If you've played the game or studied any videos closely, then you may have noticed that the wires light up as the signals active within them. Well, irritatingly, these visual effects are only a representation of the binary signals, which we know are garbage in your analogue device and it's actually quite hard to ignore them when you are debugging.
So, this was an overview of the basics of analogue processing, and whilst the end bit of that example may have seemed a little unbasic (that's a word, right?), all I've done is some of the standard analogue processing tools. The logic network in question has 9 components in it, and most of those were humble batteries. If we can transform a triangle wave into a sine wave using only 9 components, this should highlight how powerful this analogue signal processing is.
Obviously, generating a sine wave is not the most practical of examples and I'm sure for many of you, periodic waveform manipulation is not the first thing you think of when considering useful gameplay logic. But it's worth noting that there are entire fields of engineering that rely upon waveform manipulation to keep our lives ticking along in the cushty way that they do, so don't be turning your nose up at the lovely, lovely sine waves
Anyways, the logic blog has always been about technique and methodology, expanding or improving the toolsets available in an application agnostic manner. The little bits of signal limiting and subtraction presented here are useful techniques to know and will lead onto many applications once you become comfortable with solving problems in an analogue manner.
I'm not entirely sure what I'm doing next time, but it's likely to be some extensions of this analogue signal processing, including addition and signal sampling. Hopefully, for all our sakes, it'll work out a little shorter than this one.
*Note to Digital Systems: I didn't mean what I said there, I still love you
LBP2, at time of writing, is still in beta and it's possible that some of the techniques described here will not work 100% in the final release, and so any of this information is subject to change.