Hi,

Sometimes a "picture" can be helpful, for example the "Transfer Characteristic" Graph here. Apologies for the "ASCII Art" but it's easier to edit than using a separate drawing App.

The graph (diagonal line) shows how an "input" value on the horizontal base line (the X-axis) is to be converted to an "output" value on the vertical scale (the Y-axis). Here, the (straight) line starts at 75 for the "zero" input value and ends at 225 corresponding to the highest input (X) value. The highest input value might be 255 or 256 depending whether a byte or word value is being used (setting a byte to 256 makes it overflow and read as zero). For example to "map" the input (X) value of 128, we look for 128 along the X-axis and move exactly vertically until we reach the line, then exactly horizontally to read from the Y-axis, i.e. a value of 150 here.

Code:

```
Y
/|\
| !
225|-----------@225 \
| / ! )
| / ! )
150|<----/ | } 225-75=150
| / : ! )
| / : ! )
75 @-----:-----+ /
| : !
| : !
0 O+++++#+++++#++++> X
0 128 256
```

A way to "simplify" the graph is to move the graph line downwards (or sideways, or upwards) until it passes through the "origin" (where X and Y are both zero). To do this here we must subtract 75, which gives a clue that at the end of the calculation we should add the 75 back in. Now, we can calculate the gradient of the line, i.e. it rises by a value of 150 as it moves across the 256 points of the X-axis, so the gradient is 150/256. To calculate the result, we multiply the input value by the gradient and add the offset that was removed, so the calculation becomes

**b0 = b1 * 150 / 256 + 75** . If we're working with larger numbers then we can reduce the

**150 / 256** to

**75 / 128** or maybe use 255 to reduce to

**30 / 51**, but there is still a severe risk that the intermediate calculation will overflow a word value of 65535.

However, the X2 chips (only) have the "

***/**" operator which performs a multiplication but then "automatically" divides by 256, so we can reduce the "Subroutine or Macro" to

**b0 = b1 */ 150 + 75** . The M2s (and X2s) have the "

******" operator, which may seem more confusing because it multiplies and then automatically

**divides by 65536,** but this can be very powerful. Since it divides by a value that is 256 times too large for our application here, we need to multiply by 256 to compensate, so in an M2 we could write

**b0 = b1 * 150 ** 256 + 75** , or better, pre-calculate the known (fixed) part of the multiplication to become

**w0 = w1 ** 38400 + 75** . This has two advantages; firstly, because it divides by 65536, it can

__never__ overflow, regardless of how large are the two word values. Also, we can have very "fine" control of the gradient, because it could be 38399 (/65536) or 38401, etc. However, since it divides by 65536 we must be careful to use it only with "large" numbers, or we will just end up with zero(s).

Things can get more "interesting" if we consider several of these "graphs" joined side-by-side, for example four to give a range of X values from zero to 1023 (or 1024). The X-range can be calculated (or "scaled") in many ways, but in particular it's the direct output from a

**READAC10** command, for example from a Pot. Then we can use the High byte of the Input Word to select which of the four sections of the larger graph to read. For example a section (numbered 0) to the left of the above map (number 1) could be a line from the origin (X=0, Y=0) to Y = 75 (i.e. a gradient =

**75** / 256) to link to the original line (gradient =

**150 **/ 256) and then the next section could have a gradient of

**300** / 256 to reach a Y-level of 300 + 225 = 525 , and a final section could continue to 1023, with a gradient of

**498** / 256 . That gives a "logarithmic" transfer characteristic, which might give a better subjective effect with a potentiometer controlling for example PWM for LED brightness, or as an Audio Volume control (Log or Decibel "Law").

It's not necessary to write separate Subroutines or Macros for each "section", a single routine can use a Lookup command or a Table. For example

**READADC10 w1 : LOOKUP b3 , (0 , 75 , 225 , 525 , 1024) , WYleft **for the starting level of the line. The ending level could be read after incrementing b3, or from a second

**LOOKUP b3 , (75 , 225 , 525 , 1024) , WYright** . Calculate the gradient as

**WYright - WYleft** (/256) and the "Output" value becomes

**W0 = b2 */ gradient + WYleft** . For a large number of "sections" (perhaps 8+) a READ or READTABLE structure is faster and more efficient. But unlike the LOOKUP, a Table can contain only Bytes, not Words, so

**WYleft** and

**WYright** each must be read from separate bytes. A useful "trick" is that (because only the low byte of any word is stored), we can convert the above Lookup to a

** TABLE (0 , 0 , 75 , 0 , 225 , 0 , 525 , 2 , 1023 , 3)** where the bytes alternate as Low , High , Low , High , etc., but we easily can still see the content. However, we must multiply b3 by 2 before READing the first byte, and then (auto-) increment for the next 3 bytes, for example:

** READTABLE b3 , WYLeftLo , WYLeftHi, WYRightLo , WYRightHi **.

Finally a quick "advert" that this method is further expanded in my

CODE SNIPPETs to provide "advanced" mathematical functions such as Sine, Cosine, ArcTan, Log and Exponential, etc., at a higher resolution than is built into the X2. Obviously much more complex Program code, but it uses only 4 variables, three of which are Words, because it can span almost the full range of Word values.

Cheers, Alan.