Logic Blog

Analogue Logic 3 - DAC & ADC

Rating: 8 votes, 5.00 average.
Ana.logue Signal Processing
Preaching to the Converted

Part 3 - Dealing with Signal Duality - Conversion Techniques

Well, it's come to my attention that binary is, in fact, not just for n00bs, despite what my blog may have said a couple of weeks ago. Digital systems are actually bloody useful and quite fantastic. You see, this world of analogue signal processing may well be relatively spangly and new and it can do a whole bunch of stuff that digital systems can't, but nothing's perfect and analogue systems have some major drawbacks.

Most significant of these drawbacks is the lack of decision-making. You see, it's all well and good being able to take some input values and do a bit of number crunching, but the outcome is all a bit... vague. All we can directly do with that is control speeds, strengths and brightnesses of things. Sometimes that's great and it's exactly what you want, but for the most part, it's not that exciting.

Digital systems, on the other hand, are anything but vague - there is no ambiguity between a 0 and a 1. Realistically, what we need is the ability to use a digital signal control the parameters of an analogue calculation and the ability to make digital (TRUE / FALSE) decisions based upon an analogue system. What we need is a range of conversion techniques.


1. Digital to Analogue Conversion

The purpose of Digital to Analogue Conversion (DAC), in a broad sense, is to conditionally modify the inputs to our analogue system - the example I gave the other day was "if we are in the air, set maximum limit on player control to 60%". The first part of that sentence is digital (you are either in the air or you are not) and the second part is analogue (a maximum limit on the value of user input).

1.1 Basic Digital to Analogue Conversion:
Probably the simplest methods of Digital to Analogue Conversion is the following:

fig 1.1.1 Simple Battery in a Chip DAC

Simple as that, a battery inside a microchip. The microchip enable input (on the bottom of every microchip) responds only to the digital component of the input signal and will act as a switch to turn everything inside the microchip on or off. In this case, everything inside the microchip is in fact just a battery, so what we have achieved is to create an on / off switch to the battery.

One of the useful things about the battery is that you can set the analogue value of it's output to be any integer in the range -100 to +100. This means that when we switch on the battery, we can generate any (fixed) value we wish. When we switch it off it will be stuck at 0 though. We can't directly modify the off=0% behaviour, but we can do some analogue processing afterwards if need be (as we will in a bit).

We can now assign an arbitrary analogue value to any digital signal, or to use some technical parlance, we have given it a "weight". This directly gets around the analogue / signal duality issue, by explicitly forcing the analogue signal to have some direct relation to the digital.

1.2. Example: Limiting Air Control
For the example of limited air control, conceptually:
  if ( inTheAir )
      maxControl = 60%

      maxControl = 100%
So we need to translate a digital TRUE to an analogue 60% and a digital FALSE to an analogue 100%. If we use the battery in a microchip method then we have to produce a 0% at FALSE, so it makes sense to utilise our NOT gate function on the battery output, to give us ( 100 - 0 ) when FALSE, which is what we actually need. If we then set the battery value to 40%, we should get 60% output from the NOT gate when we switch on the battery:

 input  | Battery | NOTed Output |
 FALSE  |    0%   |     100%     |
  TRUE  |   40%   |      60%     |
The entire system is shown below. The microchip is our DAC stage, with a battery inside and the analogue stick input is split, limited and then recombined:

fig 1.2.1 Air Control Limiting Device

The actual DAC section takes a digital input and either outputs a value of 0% or 40% - in a way this is still a kind of digital system, it's still on or off and nothing in between, but we have just assigned a weight to that digital signal and so bridged the gap between the worlds of analogue and digital.

1.3. More Complex DAC
This is a bit of a contrived example, but it's kinda cool. Once we can take some binary signals and apply weights to them, we can easily create a device to convert a binary-encoded number into analogue. For simplicity's sake, we will use a 7-bit unsigned integer - which is capable of representing values between 0 and 127 (inclusive), which is close to the range we have for our analogue signals.

Spoiler Spoiler - geekNotes: On Binary Encoding of Unsigned Integers

The implementation is actually quite simple. We can weight each bit using the "batteries in microchips" method and then just pass those values into an adder from last instalment of the logic blog.

However, our sum is potentially greater than 100, so we have to handle overflow. If you are used to binary systems, then you would be used to putting b6 on the left and side, which might lead you to make that the first stage of your addition (that's what I'd naturally do, anyway). Don't. This DAC system is a perfect example of where a re-ordering of operations, discussed section 2.8 of the adders blog entry, will save you a fair bit of logic. I know, for a fact, that ( b5 + b4 + b3 + b2 + b1 + b0 ) can never be greater than 63, so if we ensure that b6 is the last element to be added on, then we only need one overflow stage as shown:

fig 1.3.1 Seven Bit DAC Circuit

So, whilst 7-bit DAC possibly isn't your most useful device; from an academic point of view it's a useful example of the design constraints associated with addition and overflow from last time - make sure you know what your inputs are. Plus anything about encoding in binary seems to have a bit of geek kudos to it. I did actually use this system to create the numeric display from binary inputs in my Inter-Level Logic Communications demo, as I already had a analogue - numeric display device knocking about, so it was quicker to do conversion from binary to analogue to display data than to create a custom circuit to do it directly.


2. Digitally Switched Relay

Before we move onto Analogue to Digital Conversion, there is a device that doesn't quite fit into the category of conversion, but is fundamentally involved in our fusion between analogue and digital: the relay. A relay is a device that will conditionally pass a value through it. Typically it will have 2 inputs - one for the input signal and one for the "enable" signal. If the enable is active, then the output will reflect the input signal.

2.1. AND Gate Relay
In binary, this basically boils down to an AND gate and sometimes this is also true in the analogue world, remembering that AND is min(). If we activate the AND-gate relay using something like a grab switch, which only outputs 0 or 100, we find that:
o = min ( i, g )
so when the grab is not activated (g=0):
o = min ( i, 0 ) = 0
And when the grab is actived (g=100):
o = min ( i, 100 ) = i
However, because we are interpreting the output of the AND as analogue, the activation input must also considered to be analogue. Therefore this system is working purely in analogue, and as such only works for activation signals that are fixed at a hard 0 or 100 analogue signal (grab, impact, button, etc)*. Annoyingly, one of the most useful ways to use a relay is with a timer as the activator, switching on the relay for given period of time, then it shuts down again.

In these scenarios we are screwwed using the simple analogue min() function system - as demonstrated graphically below, using the example of a timer:

fig 2.1.1. Example of issues with AND Gate Relay in Analogue

Above you can see the value of an arbitrary signal and a timer signal that we are attempting to use to activate the output. In this particular case I've modelled the timer with an inverted output and triggered using the reset input, which is what gives us this particular triangular waveform.

Using the AND gate relay in this case will fail as shown below, where the dotted line is the correct output and the solid line is what the AND gate outputs. It's just a min() function on the analogue signals, so it breaks as soon as the timer drops below the signal of interest.

fig 2.1.2. Comparison of Correct VS Actual AND Gate Outputs

2.2. Digitally Activated Relay
However, if you recall the behaviour of the digital component of the timer output, which goes to 1 as the timer reaches 100%, and stays there until it goes back to 0%. So it should be clear that the digital component of the timer is active for 2 seconds, so if we can use that to trigger the relay, we will have the correct behaviour. Much like with our DAC, the simple way of achieving this is to build the relay out of a microchip. If you wire into the microchip, and create a circuit node, then wire from that back out of the microchip, you have a chip as shown below:

fig 2.2.1 Basic Microchip Implimentation of a Digitally Activated Relay

This microchip relay thing is a neat technique to use as it works for both binary and digital signals and is pretty efficient if you have multiple signals that need to switched by one enable signal. The following shows a 5-signal microchip relay, which is pretty neat and tidy:

fig 2.2.2 Relay Activating Multiple Signals

One great use for the relay is disabling the player inputs from a controlinator. If you pass them through a micochip you can simply turn the chip off and at that point you have a instant "disable player input" control.

One important thing to not here is that you should not, under any circumstances, remove the circuit nodes from inside the microchip in this device. If you do, the relay will still work, the microchip will just have an input wired straight to the output, but sometimes when recalculating wire routing, the system will re-route that wire outside the relay and break your lovely logic creations. Oh noes!

Spoiler Spoiler - geekNotes: On the Subtleties of Enabling Microchips


3. Analogue To Digital Conversion

So we've covered stimulating and manipulating our analogue systems using digital inputs, but what about going the other way? As mentioned in the introduction, analogue doesn't have the ability to make decisions, so the ability to generate digital signals from an analogue source is very important to us if we want to get a whole lot of use out of the analogue processing tools available to us.

3.1. Thresholding
The simplest form of analogue to digital conversion is thresholding. Basically, we take an analogue signal and say, "if the value is greater than x, do that thing that you do". As it turns out, thresholding in LBP2 is remarkably simple, yet the function is cunningly hidden away, in the sequencer.

The sequencer has an input type called "positional", which interprets the absolute value of the analogue signal component into a position on the sequencer. So a 0% input signal will be at the far left, 100% at the far right and 50% is in the middle. The wonderful thing about this is that the response is instantaneous, as soon as your analogue signal changes, the sequencer position moves to the correct position.

Knowing this, it's incredibly easy to activate a binary signal when an analogue signal goes over a fixed threshold. For example, the following will output a digital TRUE when the analogue input from the timer is greater than 50% and a digital FALSE, when it is not:

fig 3.1.1. > 50% Threshold Circuit

Of course, this method will give you an upper boundary, or a lower boundary, but it can easily be adjusted to give both, or even multiple boundaries. The example below will output a 1 if the input value is between 30 and 50, or greater than 80:

fig 3.1.2. Multiple Threshold Circuit

Note the OR gate inside the sequencer is not actually affected by the sequencer position. In this case it's simply convenient to keep the OR gate inside the sequencer as it allows you to have a single output wire, which cleans things up a fair bit, encapsulating the whole ADC stage into a single component.

3.2. Comparators - Greater / Less Than
Thresholding is great if you have some fixed maximum and minimum values for your range, but sometimes you will have ranges that move. Of course, if you want to just swap between one range and another, then you could switch thresholders quite easily, but this doesn't help if you want the activation range to be more dynamic. What we really need is a method for comparing 2 analogue signals, which is again pretty simple to do. To create a system where input 1 must be greater than input 2 to activate:
i1 > i2
i1 - i2 > 0
So, we simply need to find the difference between i1 and i2 (using subtraction) and if the difference is greater than 0, then we know that i1 > i2.

However, note above where I said that the positional sequencer is one of those devices that takes the absolute value of its input. This means that all negative values will be treated as positive, which leads us to an issue with the above equation. In this case it means that any non-zero difference will trigger the output. So as is often the case when subtracting, we split the signal and take the positive component only, to create our comparator as shown:

fig 3.2.1 Analogue Comparator

Note the battery placement here. It actually takes up the entire width of the sequencer, but at exactly zero the sequencer does not trigger the battery. As we have split the signal, this means that any negative value will also read 0, so we have accurately created the "greater than" comparison.

3.3. Comparators - Equality
In the example above we inadvertently made an inequality test, before we added the splitter. So if we were to invert the "not equals to" test, then we have a "not not equal to" test. Or, if you prefer an "equal to" test. Job done.

Well, sort of. Using that method, the difference between the two signals would have to be exactly zero, they really would have to be identical. However, in analogue systems, depending on what your input sources are, having two signals at exactly the same value is quite rare, especially when you consider that the granularity of our analogue signals is at least 0.001% (new estimate by me, using score sensors as source data) and possibly less. So we will often need margins of error on concepts like equality.

Again, this is very simple, remove the splitter and place the battery as shown:

fig 3.3.1. Equality Comparator with 5% Margins of Error

Hanging the battery over the back of the sequencer allows you to detect at 0% (unlike before), and up to a certain percentage. The above detects anything from 0-5% so as long as the absolute value of the difference between the two inputs is smaller than 5, we have an "equality". To clarify with examples:

  i1  |  i2  | Output |
  15  |  17  |  TRUE  |
  17  |  15  |  TRUE  |
  95  |  94  |  TRUE  |
  95  |  89  |  FALSE |
  89  |  94  |  FALSE |
The significant point being that it doesn't matter which which is greater, as long as they are within 5% of each other then we are golden.

3.4. Comparators - Dynamic Ranges
We covered static ranges under thresholding, but if you wish to have a dynamic range, you will need to use a mixture of the techniques above. In the simplest form, a dynamic range has a upper bound and a lower bound that can move and you can determine whether you are in the range, by testing for each boundary condition separately and ANDing the result. So for upper and lower boundaries of bhi & blo:
bhi > i > blo
Which becomes:
( bhi > i ) AND ( i > blo )
or, if you prefer:
( i < bhi ) AND ( i > blo )
Which is a horrible mix of analogue and digital systems all munged into a single equation, which is none too pretty, but should be vaguely straightforward to understand: To be in range you must be smaller than the high boundary and greater than the low boundary.

However, we may have dynamic ranges that are better described by a center point, where the input has to be within a fixed distance from that center. This is actually the same scenario as the equality with fixed margin of error, described above. Or you could describe your range as the lower boundary that moves and the range is fixed, so
bhi = blo + 15
Where 15 is the size of the range. For this we use the following:

fig 3.4.1 Sliding Range with Fixed Width

Noting that both upper and lower boundary are tested for inside a single comparator. In addition to not having the second comparator, we also don't need to generate the value of the upper boundary - it's implied in this system, so you don't have to bother with an adder circuit or anything fiddly like that.

We can also have systems where we input a center point and a size of the range, or lower bound and size of the range, which would involve a bit of analogue processing to generate upper and lower bounds. Really it depends on what exactly you are testing for. But depending on your exact needs and the nature of the dynamic range in question, you can push more of the system into the analogue part, more into the digital part or more into the comparator(s). It's actually a remarkably flexible system and there are a lot of different techniques that can be employed here, but I doubt any of us have the attention span to go through each one in minute detail.

3.5. Further ADC
Ummmm, there isn't really anything more on ADC... That's it. Subtraction is the bestest function ever and sequencers with batteries in are win. So much win in fact, that you map a complete bitpattern for 7-bit binary encoding onto a sequencer and have a full analogue to digital conversion, which I have of course done, for funzies. You can then detect whether the input is positive or negative and add a sign bit as appropriate (to give 8-bit signed magnitude binary and encode from -100 to 100). Alternatively you can generate binary 2-s compliment.

More usefully, you could create a device to directly convert an analogue signal onto a human readable display, which is how I know all of these analogue systems work the way the theory suggests they should, because I have a probe:

fig 3.5.1 Mah Awesome Logic Probe


Quantisation & Analogue Look-Up Tables

Having covered DAC, ADC and the relay device, I'm going to touch briefly on a couple of concepts that I suppose you could consider analogue to analogue conversion.

4.1. Quantisation
Analogue systems are continuous and allow us to represent, conceptually, an infinite number of states. Obviously not strictly true in LBP, but there are a hell of a lot of states, probably more than we can perceive using the tools available to us, so to all intents and purposes it is continuous. Digital, on the other hand, allows us to represent 2 states (or 3-states). Sometimes however, you need the range of values available in an analogue system, but the imprecise nature of a continuous range is unwieldy and overall it's an annoyance. Take the example earlier of the equality function, where we added margins of error because it was so unlikely for the signals to actually be at exactly the same value.

In a more general sense, we can convert the analogue component of a signal into an arbitrary quantised system, whose values appear to be part of the continuous analogue range, and can be processed as such, but only certain, predetermined values are available.

Or, to be a little bit more informal (and probably a hell of a lot clearer), we can introduce the concept of rounding. No longer do we need to have a value in the continuous range -100 to 100, we have a signal that could be one of
{0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}
It will never be at 63, or 38, or 6, ect. and if it changes from one of the listed values (quantum states) to another, then it will jump instantly between them. The use of this is that it gives a much simpler system of numbers to work with, yet we can use analogue processing techniques. It gives a signals that aren't quite so vague as true analogue, but distinctly more flexible than digital.

Obviously, implementation comes down to batteries in a sequencer, you just select the range 5-15 and place a battery there that has an output value of 10, then a between 15-25 you place a battery with output value of 20, etc. You then OR the 10 signals to get the currently selected value.

4.2. Analogue-Indexed Lookup Tables
The analogue indexed lookup table is a simple extension of the quantisation technique above and essentially consists of arbitrary values in the batteries, rather than sensible roundings. You can create complex mappings of input to output using this, one of which would allow you to create a power function (square, cube, etc.) with accuracy to the nearest 1% (or any accuracy you desire). But, that would truly be an abomination...

I'm sure there are plenty of less ugly applications that could use a look up table... I just can't think of many. Overall they can be used to approximate just about any signal processing function on a single input, as long as you are willing to take the hit on accuracy and can be bothered to place all of the batteries required. Of course for things like zero-latency power functions, for which we have no other methods (as far as I'm aware), the inaccuracy is maybe not such a big deal, compared to being able to produce the function in question.



So, it would appear that I have written a few thousand words about putting batteries into microchips, which is quite impressive in itself, really. What's more impressive is the amount of additional functionality this provides us with. Being able to switch between the analogue and digital signal processing models at will, and the introduction of thresholding / decision making opens up a whole world of hybrid analogue / digital logic. No longer are we constrained to the inputs of our analogue signals being raw sensor data, and the outputs no longer have to just be a simple speed value.

Next time I sharn't be doing a worked example as promised, I'm shall instead be covering sampling, storing and scaling, as I finally cracked the ability to multiply an analogue signal by any constant rational number. Which includes multiplication by numbers smaller than 1, A.K.A. division. Which, I think, is pretty darn impressive. I'll also look into approximating multiplication of two or more inputs, in an attempt to beat down the luddites, naysayers and heretics all clinging so desperately to their pistons!

*OK, technically not true. It only works for enable signals that can be guaranteed to always be at 0% when deactivated and greater than the value of the relay main input when active.

Updated 10-27-2010 at 09:27 AM by rtm223

Logic Blog


Page 2 of 2 FirstFirst 1 2
  1. rtm223's Avatar
    No problem, your English is fine

    That's... weird. The cell's SPEs have 128bit data width, but I was under the impression that they only worked on 32-bit or less values (the 128 bits being for SIMD operations), though I could be wrong.

    On the other hand, it could just be floats that are used. A single precision float can encode down to 10-38. Considering that 100% doesn't need to be represented as true 100 in the float, it is possible that the true floating point value is scaled to allow for granularity that low.

    It may seem odd to encode the logic data as floats - a 16 bit int would probably have given us sufficient precision. However, the historical implementation of analogue signals would have been to take tag sensors (detecting physical properties, in floating point values), outputting to physical properties in floating point values, so in LBP1 it would have made sense to not convert to ints in the wire. For the sake of backwards compatibility, the convention of float was probably retained.

    At a guess, I'd say we have floats in our analogue signals. Though most of the above is sheer speculation, but it fits the information available.

    Side note: you can get instant response from upscaling using adders: double a signal by adding it to itself: (2i = i+i). I've also noticed that the sequencer's rounding behaviour isn't pleasant when for the positional signals. Downscaling does require use of timers for most things though.

    I found that placing the batteries in the way you describe puts the signal right on the border of 2 batteries when the signal is a whole number (using batteries / counters for reference). I've been placing my batteries so that the whole numbers land right in the middle of a battery, so that my integer display probe will report a value of 40 for signals in the range 39.5 - 40.5. not a big deal, but worth mentioning.
  2. upsilandre's Avatar
    Quote Originally Posted by rtm223
    That's... weird. The cell's SPEs have 128bit data width, but I was under the impression that they only worked on 32-bit or less values (the 128 bits being for SIMD operations), though I could be wrong.
    SPE also work on 64bit data but bad, for fast 64bit process need the custom IBM''s cell use for supercalculateur, the powerXcell ( PS3 use the Cell BE) but you can emulate 128bit or more with some 32bit operations but you have surely right, they simply use float

    Side note: you can get instant response from upscaling using adders: double a signal by adding it to itself: (2i = i+i).
    oh yes of course. i have already rectified my "ammeter" for 0.1% granularity (with x4 upscaling for fine down the last sequencer),thanks

    I found that placing the batteries in the way you describe puts the signal right on the border of 2 batteries when the signal is a whole number
    yes i seen that
    Updated 11-02-2010 at 09:10 PM by upsilandre
  3. Tygers's Avatar
    I ran some tests of my own and I think I can say with pretty high confidence that they use single precision floating point for the analog values.

    First to test the number of bits in the significand, I created a binary decomposition chip - basically it takes the current value, turns it into a 0 or 1 (0 = 0-50%, 1 = 50-100%) then doubles it. The output of one chip is then fed into the next chip and the process repeats. As an input I used a counter so I could set irrational fractions. For ease of use, I fed this through an inverter so I could quickly go through 2/3, 4/5, 5/6, 6/7, and so on. I layed together about 48 of these binary decomposers, but no matter what I fed in, only the first 24 would ever show a 1 bit, after that the value was true 0. This is EXACTLY the number of bits you would expect to see on a single precision (32 bit) floating point number.

    Since the step involves an inversion, this also nicely eliminates the exponent from the test. The way floating points work, a very small number can be represented, but once you have a large number, the precision drops down to the significand only. This means that no matter the scale they are using, this will show up.

    Next I wanted to test the exponent. Unfortunately they do not make this easy, since values are clamped at 100%, and there is no native divide by 2. So I picked something close to a power of 2 and divided by 255 (8.5 sec timer on the divider). I also wrote a C program to do the same division natively. The result is 18 divisions by 255, followed by 3 divisions by 3 before the value becomes 0. This matched my C program exactly.

    Finally, the final proof that it is floating point... Once you divide by more than 2**24, running the non-zero value through two NOT gates results in a zero value, exactly as you would expect if you subtract a very small floating point value from 1.
  4. Tygers's Avatar
    As an addendum to my previous post, the fact that it is single precision floating point is going to be largely irrelevant to us; since the most basic operation (Addition) requires an inversion, we've basically got 24 bits of precision; anything else will end up rounded to 0 or 100%.

    I also have a meter that produces as many decimal places as you want. Basically it comes in two different flavors. One is a sign detector with a display for -1, to show the 100s place and negative value. The rest all do the same thing; they convert the signal in to two decimal digits, scale it by 100, and output it to feed into the next module. You can stack them as far as you want; though after 7 places, the precision of 24 bits breaks down.

    The downside of my meter is that it does no rounding. So with just two places, it often shows 1 less than the value. But if you add more digits, they will show up as .99, so I usually add one extra digit after the decimal point. However I consider this a feature, as the .0000001 difference can effect which bar in a sequencer is selected.

    If anyone wants a copy of my meter let me know and I can put up a level to share it.
    Updated 02-15-2011 at 10:30 PM by Tygers
  5. toast's Avatar
    i have no clue what this means.. o.o
    but i sure am going to play around with a few of these logics xD
Page 2 of 2 FirstFirst 1 2