Talking Electronics PIC Theory

Performing MATHS

The '508A does not have an inbuilt maths co-processor and it seems to have very few mathematical instructions in its instruction-set. 
So, how do you carry out mathematical operations?
Firstly, very few programs require mathematical operations but when  one is required, there are a number of ways of carrying them out. 
In any program, there are different "levels" of mathematical complexity. Merely setting or clearing a bit can be considered as adding or subtracting  from a file and rotating left or right is equivalent to multiplying  or dividing. 
What we really mean about "Maths" is adding, subtracting, multiplying, dividing, percentage, etc - all those features found on a $10.00 calculator. 
The '508A is not a calculator and very few programs require "calculator-type" operations. However, add, subtract, multiply and divide are available, once you know "how." 
For instance, multiplication can be performed with a series of additions  and converting a value to another value can be achieved via a table  - rather than using a mathematical equation. Thus a table can be equivalent  to percentage or produce a result equal to dividing by 0.075 etc. 
The amount program space required to produce a mathematical operation  depends on the accuracy you require and how much room you can afford  for the table or routine. 

Here are some of the ways to produce mathematical results:


One of the simplest mathematical operations is addition and subtraction. The '508A has instructions to INCrement or DECrement a file. This is  simply "ADD one" or "SUBTRACT one" from a file. You cannot INCrement or DECrement the working register (W), so values  have to be moved to a file for these operations to be performed.
On the other hand, you cannot ADD a number (literal) to a file so the number (01 to FF) is firstly put into W then the instruction ADDWF is performed, where the literal is ADDed to the W register. 
Two files can be added together by firstly loading one file into W (such as MOVF 0C,0 - where F is the first file) then implementing the instruction: ADDWF where F is the second file, such as 0D.Suppose file 0C contains 45h and 0D contains 83h.

The instructions are: MOVF 0C,0     ;45 is moved into W
                             ADDWF 0D,0   ;the result is put into W

or:                         MOVF 0C,0     ;45 is moved into W
                             ADDWF 0D,1   ;the result is put into file 0D

Two files can also be added together by decrementing one file and incrementing the other in a loop. The instruction DECFSZ is used to detect when one of the files is zero and the program comes out of 
the loop. The other file will contain the sum of the two values. 
The advantage of doing this is the incrementing file can be tested during each loop for a particular condition and the program can exit the loop before the two files are fully added, if required.

There are a few technical points you must know when incrementing or decrementing. 
A file incremented past FF "rolls over" to 00. If a file containing 00 is decremented, it "rolls over" to FF.
There are two ways to add a number (literal) to a file. 
1. by successive increments, and 
2. by adding a literal to W then ADDing W and the file together. 
If a file has a literal ADDed to it, the result may make the file larger than the required value and a false decision may be made. 
It is better to increment a file by successive INC instructions, via a loop. It can be tested after each pass of the loop to see if it has reached a particular value.
To create a loop, a file is loaded with a value and decremented to zero. The instruction DECFSZ decrements the file and causes the program to go to one of two locations, when the file is zero. 
If a condition is created within the loop, such as reaching a particular value, the program can go to "label A" where other operations can be carried out. 


Multiplication can be handled as successive additions. Division can be handled as successive subtractions. 
Both ADD and SUB instructions are available in the '508 instruction-set. 
Performing a multiplication between two files is a fairly complex operation and the answer will produce up to four digits. This will require up to four files for the answer.
The program below shows how to multiply the number 12 in file A with the number 34 in file B. Thirty-four is added to a file twelve times. 
The value 34 must be converted to a hex value. 34 = 22h. But since the program has a decrement before any operation is carried out, we must load the file with 13! This is a clever programming trick! You need four files for the result just in case the two numbers are 99 x 99!

                                    ;Clear all files

Multi     MOVLW 0D         ;0D = thirteen
            MOVWF 0D         ;0D = 1st count file
X0        DECFSZ 0D          ;DECrement the count file
           GOTO X1
            RETURN              ;The multiplication is done
X1        MOVLW 22h         ;22h = 34
            MOVWF 0E,1       ;Put 22h into file 0E
X2        DECFSZ 0E          ;DEC 2nd count file
           GOTO X3
           GOTO X0
X3        INCF 16h            ;INC units file
           MOVLW 0A          ;Put ten in W
           XORWF 16h,0      ;Is file 16h = ten?
           BTFSS 03,2          ;Test the Zero flag
           GOTO X2             ;No. Go to X2
           CLRF 16h             ;Yes. Clear file 16h
           INCF 17h             ;INC ten's file
           MOVLW 0A          ;Put ten in W
           XORWF 17h         ;Is file 17h = ten?
           BTFSS 03,2          ;Test the Zero flag
           GOTO X2             ;No. Go to X2
           CLRF 17h             ;Yes. 
           INCF 18h             ;INC hundreds file
           MOVLW 0A          ;Put ten in W
           XORWF 18h,0       ;Is file 16h = ten?
           BTFSS 03,2           ;Test the Zero flag
           GOTO X2              ;No. Go to X2
           CLRF 18h              ;Yes. Clear file 16h
           INCF 19h              ;INC thousands file
           GOTO X2              ;Go to X2

A simple way to multiply a file by 2, 4, or 8 is to use the RLF instruction. 
Each time a file is shifted left, the contents are doubled. This operation shifts the highest bit into the "carrier" and the carrier bit into the lowest position (LSB) in the file. The carrier bit could be a zero or one from a previous instruction and it must be cleared before executing an RLF instruction (before each RLF instruction).
A file can also be doubled by loading it into W then ADDing W and the file together. 

A number (such as 0 to 100) can be converted to another value using a TABLE. 
Use a formula you have produced to work out values from say zero to 100 and place them in a table. Use CALL Table1, ADDWF 02,1 and RETLW instructions to access the table.
A table can be used for converting or producing "graph values," "lines of best fit," "approximations," "statistical values," "display values" or merely converting any value to another value. The table can even be a list of random numbers, as the micro finds it very difficult to produce these types of
The result of a table can be very impressive and the advantage is it does not require a complex routine. 
Mathematical operations can also be carried out (or assisted) by SETing or CLEARing a bit in a file. You can ADD or SUBtract 1, 2, 4, 8, 10h, 20h, 40h or 80h from (or to) the value of a file. You MUST know the value in the file before executing the instruction as SETing a bit that is already a "1" does not increase the value!

Two files can be compared to see if they are the same by using the XOR (exclusive OR) instruction. Place one file in the working register W and XOR W with the other file. If they are both the same, the zero flag will be set. In other words a MATCH = 1. 

The Zero flag in the STATUS register (03h) is bit 2. 


            MOVF 0C             ;put file 0C into W
            XORWF 0D          ;XOR W with file 0D
            BTFSS 03,2          ;Test Zero flag
            The micro will go HERE if different
              The micro will jump HERE if files are a MATCH

The program can be written like this:

            MOVF 0C
            XORWF 0D
            BTFSS 03,2
            GOTO D
            GOTO MATCH

Masking is the operation of changing particular bits in a file to zero. A file consists of a high nibble (the four high bits) and a low nibble (the four low bits). You can zero the high nibble, low nibble or both. An example: zero the high nibble so that the low nibble can be incremented to 9, to produce a decimal value for a decimal counter. 
To zero a high nibble the file is ANDed with 0Fh. The value 0Fh is 0000 1111. When a bit is ANDed with 0, the result is zero. When a bit is ANDed with "1" the bit is unchanged. In this case the high 
nibble is zeroed and the low nibble remains unchanged. 
To zero a low nibble, the file is ANDed with F0h. The value F0h is 1111 0000. The high nibble remains unchanged and the low nibble is zeroed. 
Masking both nibbles is merely clearing the file. (CLRF) 


Two files can be compared to see if file 0C is larger than file 0D. 

Example: File 0C = 20h File 0D = 10h
Place file 0C in W by using the instruction: 
MOVF 0C,0 ;Put 0C into W 

Subtract W (file 0C) from file 0D by using the instruction:

Test the carry flag with the instruction:
BTFSS 03,0 ;Test carry flag 

The carry flag will be 0 (CLEAR). This means a borrow occurred and thus the value in file 0C is larger than the value in file 0D. 

Example: File 0C = 10h File 0D = 20h

Place file 0C in W by using the instruction: 
MOVF 0C,0 ;Put 0C into W 

Subtract W (file 0C) from file 0D by using the instruction: 

Test the carry flag with the instruction:
BTFSS 03,0 ;Test carry flag 

The carry flag will be (SET). This means a borrow did not occur and thus the value in file 0C is smaller than the value in file 0D. 

Percentage, and other mathematical operations such as square root and trigonometrical functions are best handled via a table. Routines can be set up for these operations but the simplest is to use a calculator to obtain the results for the range you are working with and put them into a table. 

Fractions cannot be handled by the '508A so alternative methods must be employed. 
Displaying numbers such as temperature in 0.5C increments can be produced by obtaining the whole number(s) from a table and generating the fraction (the number 5) from the program. The value 40.5C 
will be produced by making the table value 1100 0000. Bit 7 will be stripped away in the program to indicate a 0.5 on the display, leaving 0100 0000 as the value 40 for the display. In this way values from 
0C to 79.5C can be produced. The decimal point is turned on via transistor or by direct access to the decimal point on the display. 

One of the most requested features of a microcontroller is the ability to produce a count for a display. 
Counters for production-lines, clocks, decrementing counters, tally counters and batch counters are all in heavy demand in industry. 
The '508 is ideal as the heart of a 5-digit counter with any feature you require, including count-up, count-down, beep output, relay output - all with one to five displays. 
You will need 4040 counter chips and/or 74c164 shift registers to expand the lines of the '508 to drive the segments in the displays.
The basis of any counter is counting to ten. A file is incremented and when the count reaches ten (0A in hex) the file is zeroed and the next file is incremented. This file is then tested for 0A and 
if not 0A, the program goes back to polling the input line for another button-press or some other form of input, such as magnetic or optical detection. 

Here is part of the routine to increment a set of files:

            INCF 16h         ;INC the units file
            MOVLW 0A      ;Put ten in W
            XORWF 16h,0  ;Is file 16h = ten?
            BTFSS 03,2      ;Test the Zero flag
            GOTO Main      ;No. Return to Main routine
            CLRF 16h         ;Yes. Clear file 16h
            INCF 17h         ;INC the ten's file
            MOVLW 0A       ;Put ten in W
            XORWF 17h     ;Is file 17h = ten?
            BTFSS 03,2      ;Test the Zero flag
            GOTO Main      ;No. Go to Main
            CLRF 17h         ;Yes. 

The count can be stored as 0-9, in the lower nibble of a set of files, such as 16h 17h etc. This will require the least amount of programming. 
If you have a shortage of files, both the low and high nibbles of a file can be used but this will require a lot more lines of program. 

Quite often a routine will seem to need a complex mathematical operation to solve a problem. 
This is out of the question with a simple microcontroller such as the '508A. So you will have to look at the situation in a different light and try to gather the information differently. 
The best solution to anything mathematically-complex is a table. Work out the co-relation between the data and the display values and generate a table. The table can be 0FFh (256) bytes long and if the remaining 255 bytes of the '508A is not sufficient, you can use the '509 chip.
Each address location can hold a value from 00 to 255 (00 to FF) and you will require a routine to convert from hex to decimal to produce a 3-digit display. Alternatively an address location will store a 
value from 00 to 99 in decimal without the need for a conversion routine. 
An address location is capable of storing a value with fractions, from 0 to 79.5 as mentioned above.
If you require a 4 or 5 digit display, the best solution is to use either a single display or set of displays and store the value in a set of files. Treat the number as a whole number and introduce a decimal point on the display. It will appear as if you are manipulating fractions!
Sometimes a display value can be generated afresh, each time it is displayed, as a "count-and-display" routine. I have found there is quite often a very simple way around a seemingly complex problem.

It just takes a fresh look at the problem to see how to solve it. 
If all fails, use a table.