FANDOM


As with most BASIC implementations, Atom BASIC includes a full complement of math and comparison functions. For the most part, Atom BASIC performs integer arithmetic, however floating point variables and functions are provided for use where required.

Integer arithmetic is preferred for most control functions because it is fast and economical of memory. The descriptions in this chapter show some of the techniques that can be used to deal with fractional values in an integer-only environment.

Users should remember that variables must be defined before use, and that each definition should be of the appropriate number type (e.g. byte, word or long) for the functions used. Most functions will work with all variable types; exceptions are noted in the function descriptions.


Number Bases Edit

Although all calculations are handled internally in binary, users can refer to numbers as decimal, hexadecimal or binary, whichever is most convenient for the programmer. For example, the number 2349 can be referred to as:

  • 2349 or d'2349' (decimal notation)
  • $092D or 0x092D (hexadecimal notation)
  • %100100101101 (binary notation)

Note: Leading zeros are not required for hex or binary numbers, but may be used if desired.

If you're planning to use signed integers (sbyte, sword, slong) it's probably a good idea to stick to decimal notation to avoid confusion.


Integer Math Functions Edit

The math functions described in this section all use integer arithmetic (unless otherwise stated). For floating point functions see Floating Point Math on page 64.


Operator Precedence Edit

The ATOM-Pro uses standard algebraic syntax. In the ATOM-Pro 2+2*5/ 10 = 3. This is because in the ATOM-Pro each math operator has a precedence. The multiply and divide operators have equal precedence. In the above calculation 2*5 will be calculated first (equaling 10), then the divide by 10 (equals 1), then the addition of 2 (equaling 3). You can use parenthesis to force specific orders (e.g. ((2+2)*5) /10 would yield a value of 2).

Order Operation
1st NOT, ABS, SIN, COS, - (NEG), DCD, NCD, SQR, RANDOM, TOINT, TOFLOAT, BIN2BCD, BCD2BIN, ~(Binary NOT), !(Binary NOT), NOT(Logical NOT), FSQRT, FSIN, FCOS, FTAN, FASIN, FACOS, FATAN, FSINH, FCOSH, FTANH, FATANH, FLN, FEXP
2nd Rev, Dig
3rd MAX, MIN
4th *, **, */, /, //
5th +, -
6th <<, >>
7th <, <=, =, >=, >, <>
8th &, |, ^, &/, |/, ^/
9th And, Or, Xor


Out of Range Values Edit

Warning: Out of range values can occur if the limitations of number types (see page 36) are exceeded. The Atom BASIC compiler does not warn the user of out of range values. It's your responsibility to make sure variables are appropriately defined.

Out of range conditions can occur if, for example, executing a function produces a result with a value greater than the target variable is capable of storing. For example, in the following program segment:

ant var byte
bat var byte
cat var byte
bat = 12
cat = 200
ant = bat * cat ; * is the multiply function

"ant" will not have the expected value. This is because 12 x 200 = 2400, a value too large to fit into a byte variable. To see what actually happens, look at the numbers in binary form:

bat = 12 decimal = 1100 binary cat = 200 decimal = 11001000 binary bat * cat = 2400 decimal = 100101100000 binary (12 bits)

Since "ant" can't hold a 12 bit number, the lowest 8 bits will be stored in "ant", and the result will be a = 01100000 binary = 96 decimal, which is incorrect. You won't be warned of this, so take care to make sure the target variable is large enough to handle the full range of expected results.


Unary Functions Edit

Unary functions have only one argument and produce one result. In the list below, "expr" is any variable, constant or valid mathematical expression.

Important: These functions don't work with floating point numbers. (See the floating point functions on page 64.)

Function Description
- expr negates the value of expr
ABS expr returns the absolute value of expr
SIN expr returns the sine of expr
COS expr returns the cosine of expr
DCD expr returns 2 to the power of expr
NCD expr returns the smallest power of 2 that is greater than expr
SQR expr returns the square root of expr
BIN2BCD expr converts expr from binary to packed BCD format
BCD2BIN expr converts expr from packed BCD to binary format
RANDOM expr returns a random number (32 bit) generated with seed expr


- (negate) Edit

Negates the value of the associated expression. The result will be a signed value; the target variable should be defined as such.

Example

If temp is a signed variable, and "mark" has a value of 456, the statement:

temp = -mark

will assign the value of -456 to "temp"


SIN, COS Edit

Note: Consider using floating point equivalents for these functions. See page 64.

For use with integer arithmetic, some modifications to the usual use of sine and cosine are made. For example, in floating point math, the expression:

ans = sin(angle)

where angle is 1 radian, would return a value of 0.841... for ans. In fact, the sine of an angle must always be a fractional value between -1 and 1. Atom BASIC can't deal with fractional values, however, so we've modified the use of SIN and COS to work with integers.

Because we are dealing with binary integers, we divide the circle into 256 (rather than 360) parts. This means that a right angle is expressed as 64 units, rather than 90 degrees. Thus, working with Atom BASIC angular units gives you a precision of about 1.4 degrees.

The result of the SIN or COS function is a signed number in the range of -127 to +128. This number divided by 128 gives the fractional value of SIN or COS.

Real World Example

In most "real world" applications, the angle need not be in degrees, nor need the result be in decimal form. The following example shows a possible use of SIN with the Atom BASIC values. Suppose that a sensor returns the angle of a control arm as a number from 0 to 64, where 0 is parallel and 64 is a right angle. We want to take action based on the sine of the angle.

limit var byte
angle var byte
loop
(code that inputs the value of "angle")
limit = sin angle
if limit > 24 then first
if limit > 48 then second
goto loop
first
code to warn of excessive angle
goto loop
second
code to shut down equipment
etc...

This will warn the operator if the arm angle exceeds approximately 8 units (11.25 degrees) and shut down the equipment if the arm angle exceeds approximately 16 units (22.5 degrees).

Theoretical Example

Although most control examples don't need to work in actual degrees or decimal values of sine or cosine, this example will show how that can be accomplished. To find the sine of a 60 degree angle, first convert the angle to Atom BASIC units by multiplying by 256 and dividing by 360. For example:

angle = 60 * 256 / 360

which will give a value of 42. (It should actually be 42.667, which rounds to 43, but with integer arithmetic the decimal fraction is ignored, and the integer is not rounded up.)

Then find the sine of this angle:

ans = sin angle

This will give the value 109. Dividing this value by 128 will give the decimal value of 0.851 (compared to the correct floating point value which should be 0.866).

Note: You can't directly get the decimal value by doing this division within Atom BASIC (you would get a result of 0). However, you could first multiply by 1000, then divide by 128 to get 851 as your result.


DCD Edit

Similar to the "exp" function in some other BASIC implementations. Returns 2 to the power DCD.

Example

If the value of "num" is 7, the statement

ans = dcd num

will return a value of 27, or 128. Since the returned value increases exponentially, make sure your target variable ("result" in this case) is correctly defined to accommodate the largest value anticipated. If the target variable is too small, only the low order bits of the result will be stored.


NCD Edit

This function returns the smallest power of 2 that is greater than the argument.

Example

If the value of "num" is 51, the statement

ans = ncd num

will return the value of 6. Since 25 = 32 and 26 = 64, 6 is the smallest power of 2 greater than 51.


SQR Edit

Returns the integer portion of the square root of the argument. Increased precision can be obtained by multiplying the argument by an even power of 10, such as 100 or 10000.

Note: Consider using FSQRT with floating point numbers, see page 64.

Example 1

If the value of "num" is 64, the statement

ans = sqr num

will return the value of 8 (which is the square root of 64).

Example 2

If the value of "num" is 220, the statement

ans = sqr num

will return the value 14, which is the integer portion of 14.832..., the square root of 220.

Example 3

If more precision is required, multiply the argument by 100 or 10000. Again, using the example where "num" = 220:

ans = sqr (num * 100)

will return the value 148, which is 10 times the square root of 220.

Alternately,

ans = sqr (num * 10000)

will return the value 1483, which is 100 times the square root of 220.

Note: If you subsequently divide these results by 10 or 100, the precision gained will be lost because of the integer division. You should convert the numbers to floating point first. See page 64.


BIN2BCD, BCD2BIN Edit

These commands let you convert back and forth between binary and "packed" binary coded decimal (BCD). A BCD number is one in which each decimal digit is represented by a 4 bit binary number (from 0 to 9). Packed BCD packs two 4 bit decimal digits in a single byte of memory.

For example, the decimal number 93 is represented in binary as:

  128 64 32 16 8 4 2 1
binary 0 1 0 1 1 1 0 1

The same number is expressed in packed BCD as:

  8 4 2 1 8 4 2 1
packed BCD 1 0 0 1 0 0 1 1
 
 
 
  9 3

Example

Assuming that "ans" is a byte variable and "num" has the decimal value of 93, the statement

ans = bin2bcd num

will set ans to a binary value of 10010011 (which is 93 in packed BCD).

Note: If you choose to interpret "ans" as a decimal number, the value will seem to be 147 decimal, which is an incorrect interpretation of the result.


RANDOM Edit

The RANDOM function generates a 32 bit random number (LONG) from the seed value.

Syntax

random seed

"seed" is a variable, constant or expression having any value from 0 to 232. The seed will be treated as an unsigned number.

As with most random number generators, the random numbers generated will follow a predictable pattern, and each time the program is run the random number sequence will be the same. Two steps can avoid this problem and generate a usefully random sequence of numbers:

  1. Generate the original seed from, say, a timer value so that the result will not be the same twice in succession.
  2. Use the returned value as the seed for the next RANDOM statement.

Example

Timer A is always running, so we can read its value at any time to get a pseudo-random seed number.

a var long
a = random TCA
(code using the value of a)
loop
a = random a ; uses "a" to generate a new "a"
(code using the value of a)
goto loop

Note: The Timer A counter TCA is hardware specific. It will work on an Atom Pro but not on a Pro Plus (BAP40). On The BAP40 and soon to be Arc32 you might try using Timver B1 (TMB1)

Binary Functions Edit

Binary functions have two arguments and produce one result. In the list below, "expr" is any variable, constant or valid mathematical expression.

Note: The word "binary" means that these functions have two arguments, not that they are specifically designed for use with the bits of binary numbers.


Function Syntax Comment
+ expr1 + expr2 addition
- expr1 - expr2 subtraction
* expr1 * expr2 multiplication
/ expr1 / expr2 division*
The expressions below do not work with floating point numbers.
** expr1 ** expr2 return high 32 bits of a multiplication*
*/ expr1 */ expr2 fractional multiplication*
// expr1 // expr2 mod*
MAX expr1 max expr2 returns the smaller expression*
MIN expr1 min expr2 returns the larger expression*
DIG expr1 dig expr2 returns the digit from expr1 in the position determined by expr2*
REV expr1 rev expr2 reverses the value of expr2 bits of expr1 starting with the LSB*
* These functions are further described in the following sections.
** is read as GET HIGH BITS

If two long variables or constants are multiplied, the result may exceed 32 bits. Normally, the multiply function will return the least significant (lowest) 32 bits. The ** function will, instead, return the most significant 32 bits.

You can use both functions to retrieve up to 64 bits of a multiplication, however two long variables will be needed to store this result.

Note: The returned value does not represent the decimal digits of the beginning of the product; it is best to work with binary or hexadecimal when using this function.


*/ (fractional multiplication) Edit

Note: Consider using floating point math instead. See page 65.

Fractional multiplication lets you multiply by a number with a fractional part. The multiplier must be a long number, and it is handled in a special fashion. The high 16 bits are the integer portion of the multiplier, the low 16 bits are the fractional part (expressed as a fraction of 65535). The result, of course, will be an integer; any fractional part is discarded (not rounded).

Example

Let us say we want to multiply the number 346 x 2.5. The multiplier must be constructed as follows:

The high 16 bits will have a value of 2. We can do this with:

mult.highword = 2

The low 16 bits will have a value of half of 65535, or 32782, so:

mult.lowword = 32782

Then we do the fractional multiply:

a = 346 */ mult

which will give "a" the value 865.

A similar procedure will let you multiply by any fraction; simply express that fraction with a denominator of 65535 as closely as possible.

Note: Astute readers will notice that half of 65535 is actually 32782.5; a number we can't enter as the fractional part. This means that multiplication by exactly ½ is not possible. However, the difference is so small that it has no effect on the actual outcome of the integer result.


/ (division) Edit

Integer division discards fractional results. For example:

result = 76/7

will set the variable "result" to a value of 10. (The actual decimal result should be 10.857... but the decimal part is discarded, rounding is not done.) If your application requires fractional results, there are two possible solutions:

  1. Multiply the dividend by 10, 100, 1000 etc. before dividing. The

result will gain extra digits of precision but must be interpreted correctly.

Using the previous example we can gain three digits of precision as follows:

temp = dividend * 1000 ;dividend is now 76000
result = temp/7

Which sets "result" to a value of 10857.

  1. Use floating point numbers (see page 65)


// (mod) Edit

The mod function (short for "modulo") returns the remainder after an integer division. So, for example, 13 modulo 5 is 3 (the remainder after dividing 13 by 5).

The mod function can be used to determine if a number is odd or even, as shown here:

x var word
y var word
(code that sets the value of x)
y = x//2
if y=0 goto even ;zero indicates an even number
if y=1 goto odd ;one indicates an odd number
even
(more code)
odd
(more code)

Similarly, the mod function can be used to determine if a number is divisible by any other number.

Note: Of course there are other ways to determine if a number is odd or even, this is just one example.


MAX Edit

The MAX function returns the smaller of two expressions. For example:

x var word
y var word
code to set value of y
x = y max 13

will set x to the value of y or 13, whichever is smaller. Think of this as "x equals y up to a maximum value of 13".


MIN Edit

The MIN function returns the larger of two expressions. For example:

x var word
y var word
code to set value of y
x = y min 9

will set y to the value of x or 9, whichever is larger. Think of this as "x equals y down to a minimum value of 9".


DIG Edit

The DIG (digit) function is used to isolate a single digit of a decimal number. For example:

x var word
y var byte
(code to set y) ;say the result is y=17458
x = y dig 4 ;gives the 4th digit of y, which is 7

Digits are counted from the right, starting with 1. The DIG function will work with numbers in decimal format only. If you need to find a specific digit in a hex or binary number, use a variable modifier (see page 40).


hexadecimal

Use the "nib" modifier. Each nibble is a hexadecimal digit. Counting is from the right starting with 0. For example, to find the 3rd hex digit of the number "y" you could use:

x = y.nib2

(It’s nib2 because counting starts from 0, not 1).

binary

Use the "bit" modifier. Each bit is a binary digit. Counting is from the right, starting with 0. For example, to find the 3rd bit of the binary number "y" you could use:

x = y.bit2


REV Edit

The REV function works directly in binary, but the results may be expressed in any form. It is used to "reverse" the value of the low order bits of a number (i.e. change 0’s to 1’s and vice versa). For example:

x var byte
y var byte
x = %101110 ;this is decimal 46
y = x rev 3 ;gives g a value of %101001 or 41


Bitwise Operators Edit

Bitwise operators are designed to work with the bits of binary numbers. In the list below, "expr" is any variable, constant or valid mathematical expression.

Important: These functions don’t work with FLOAT variables or constants. Since they don’t automatically preserve the sign bit, they should be used with caution for signed numbers.

Function Syntax Comment
& expr1 & expr2 AND the bits of the expressions
| expr1 | expr2 OR the bits of the expressions
^ expr1 ^ expr2 XOR (exclusive OR)
>> expr1 >> expr2 Shift right the bits of expr1 by expr2 places
<< expr1 << expr2 Shift left the bits of expr1 by expr2 places
~ ~ expr1 Invert the bits of expr1
 !  ! expr1 Invert the bits of expr1

The examples below will use 8 bit (BYTE) values for simplicity.


& (AND) Edit

The AND function compares two values bit by bit and sets the equivalent bit of the result to 1 if both matching bits are 1’s, to 0 if either or both bits are 0’s. For example:

expr1 0 1 0 1 1 1 0 1
expr2 1 0 0 1 0 0 1 1
expr1 AND expr2 0 0 0 1 0 0 0 1

Using AND for masking

One useful function for AND is to "mask" certain bits of a number. For example, if we are interested only in the low 4 bits of a number, and want to ignore the high 4 bits, we could AND the number with 00001111 as shown here:

expr1 0 1 0 1 1 1 0 1
expr2 (mask) 0 0 0 0 1 1 1 1
expr1 AND expr2 0 0 0 0 1 1 0 1

As you can see, the high 4 bits are now all set to 0’s, regardless of their original state, but the low 4 bits retain their original state.


| (OR) Edit

Note: The | symbol is usually found on the same key as the backslash \.

The OR function compares two values bit by bit and sets the equivalent bit of the result to 1 if either or both of the matching bits are 1, and to 0 if both bits are 0’s. For example:

expr1 0 1 0 1 1 1 0 1
expr2 1 0 0 1 0 0 1 1
expr1 OR expr2 1 1 0 1 1 1 1 1


^ (Exclusive OR) Edit

The Exclusive OR function compares two values bit by bit and sets the equivalent bit of the result to 1 if either but not both of the matching bits are 1, and to 0 otherwise. For example:

expr1 0 1 0 1 1 1 0 1
expr2 1 0 0 1 0 0 1 1
expr1 XOR expr2 1 1 0 0 1 1 1 0


>> (Shift Right) Edit

The Shift Right function shifts all the bits of expr1 to the right by the number of places specified by expr2. Zeros are added to the left of the result to fill the vacant spaces. (In some versions of BASIC this is called a "logical shift right"). For example:

expr1 0 1 0 1 1 1 0 1
expr2 0 0 0 0 0 0 1 1
Shift right 3 0 0 0 0 1 0 1 1

Important: The sign bit is not preserved so this function should not normally be used with signed numbers.


<< (Shift Left) Edit

The Shift Left function shifts all the bits of expr1 to the left by the number of places specified by expr2. Zeros are added to the right of the result to fill the vacant spaces. (In some versions of BASIC this is called a "logical shift left"). For example:

expr1 0 1 0 1 1 1 0 1
expr2 0 0 0 0 0 0 1 1
Shift left 3 1 1 1 0 1 0 0 0

Important: The sign bit is not preserved so this function should not be used with signed numbers.


~ or ! (NOT) Edit

The NOT function inverts the value of each bit in a number. For example:

expr1 0 1 0 1 1 1 0 1
NOT expr1 1 0 1 0 0 0 1 0


Comparison Operators Edit

Comparison operators let you compare the values of two expressions for such things as conditional tests (e.g. IF...THEN).

Note: Comparison operators also work with floating point numbers.

Operator Description
= is equal to
<> is not equal to
< is less than
> is greater than
<= is less than or equal to
>= is greater than or equal to

Comparisons include signed numbers, so -2 is less than +1, etc.


Logical Operators Edit

Important: These operators don't work with floating point numbers.

Logical operations are used to make logical comparisons. These allow you to set ranges for conditional tests. The following operators are available:

Operator Description
AND Logical AND
OR Logical OR
XOR Logical Exclusive OR
NOT Logical NOT

Important: Do not confuse logical operators with similar bitwise operators. Logical operators return a TRUE or FALSE value that can be tested with a conditional test. They do not operate on individual bits of an expression.

Example of Use

Logical operators link two comparisons. For example:

if (a < 100) AND (a > 10) then label

This will branch program execution to "label" if the value of a is between 11 and 99, or go on to the next step if it is outside these limits.

Note: In the following sections, "comp" refers to a comparison test between two expressions.


AND (logical AND) Edit

(comp1) AND (comp2)

Returns a value of TRUE if both comp1 and comp2 are true.


OR (logical OR) Edit

(comp1) OR (comp2)

Returns a value of TRUE if either comp1 or comp 2 or both are true.

Example

if (a < 10) OR (a > 100) then label

This will branch program execution to "label" if the value of a is less than 10 or greater than 100, i.e. if the value of a is not between 10 and 100).


XOR (logical exclusive OR) Edit

if (a < 50) XOR (a > 40) then label

This will branch program execution to "label" if the value of "a" is less than 50 or if it is greater than 40, but not if it is between 41 and 49. In other words, the branch to "label" will take place if "a" is less than 41 or greater than 49.


NOT (logical NOT) Edit

This unary operator works with a single argument, and returns the reverse of its truth value. So if a comparison is TRUE, NOT(comp) will be FALSE.

Example

if NOT(a > 20) then label

This will branch to "label" if a is not greater than 20, i.e. if a is less than or equal to 20.


Floating Point Math Edit

Floating point numbers are those which are capable of including decimal fractions. They are saved internally as a mantissa (the decimal part) and an exponent (a multiplier). For example, the number 39.456 would be saved as 0.39456 (mantissa) x 100 (exponent).

Atom Pro BASIC has built-in floating point capability, including a range of functions designed specifically for use with floating point numbers.


Operator Precedence Edit

See the table on page 48 which includes floating point operators.


Unary Functions (Floating Point) Edit

Unary functions have only one argument and produce one result. In the list below, "expr" is any variable, constant or valid mathematical expression.

Important: These functions don't work with integer values.

Function Description
TOINT expr Converts a Floating Point value to an Integer value.
TOFLOAT expr Converts an Integer value to a Float ing Point value.
FSQRT expr Square Root (range: all positive values)
FSIN expr Sine (range: approx. pi/2 to -pi/2)*
FCOS expr Cosine (range: approx. pi/2 to -pi/2)*
FTAN expr Tangent (range: approx pi/2 to -pi/2)*
FASIN expr ArcSine (range: 1 to -1: accuracy suffers beyond ±0.98)
FACOS expr ArcCosine (range: same as FASIN)
FATAN expr ArcTangent (range: all)
FSINH expr Hyperbolic Sine (range: 1.13 to -1.13)
FCOSH expr Hyperbolic Cosine (range: 1.13 to -1.13)
FTANH expr Hyperbolic Tangent (range: 1.13 to -1.13)
FATANH expr Hyperbolic ArcTangent (range: 1.13 to -1.13)
FLN expr Natural Log (range: 9.58 to 0.1)
FEXP expr Exponent, i.e. e to the power of expr (range: all values)
* range is actually ± 1.74 radians

One example will suffice to show the use of these functions.

Example: TOINT

x var long
y var float
(code)
x = TOINT y

This converts the floating point number "y" to a long integer.

Note: "x" should be a long integer for full accuracy. If "x" is a byte or word only the least significant 8 or 16 bits will be saved.


Binary Functions Edit

Binary functions have two arguments and produce one result. In the list below, "expr" is any variable, constant or valid mathematical expression.

Note: The word "binary" means that these functions have two arguments, not that they are designed for use with the bits of binary numbers.

Function Syntax Comment
+ expr1 + expr2 addition
- expr1 - expr2 subtraction
* expr1 * expr2 multiplication
/ expr1 / expr2 division *


Comparison Operators Edit

Comparison operators let you compare the values of two expressions for such things as conditional tests (e.g. IF...THEN).

Note: Comparison operators also work with integer math.

Operator Description
= is equal to
<> is not equal to
< is less than
> is greater than
<= is less than or equal to
>= is greater than or equal to

Comparisons include signed numbers, so -2 is less than +1, etc.


Floating Point Format Edit

This description is provided for comparison with other systems that use IEEE floating point math. It is not necessary to understand this format to successfully use floating point numbers.

The floating point math used by the BasicATOM Pro is similar to the IEEE 754 floating point standard with the exception of the position of the sign bit (S).


IEEE 754 format: Edit

Bit 31 sign bit (S)
Bits 30 - 23 exponent (E)
Bits 22 - 0 mantissa (M)
Graphic Representation
  bit 31 bits 30 - 23 bits 22 - 0
IEEE S exponent (E) mantissa (M)

ATOM PRO format: Edit

Bits 31 - 24 exponent (E)
Bit 23 sign bit (S)
Bits 22 - 0 mantissa (M)
Graphic Representation
  bits 31 - 24 bit 23 bits 22 - 0
ATOM exponent (E) S mantissa (M)

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.