N-Bit Division Numbskull Here
Greeting All.
This is my first post, but I've been lurkin' and learnin' from this site for quite a long time. Thanks to all the regulars for your great threads. I'm an aerodynamicist by training, but like to to tinker with just about everything geeky.
I can muddle my way through BASIC, but have quite a bit of difficulty with assembler, though by necessity, I am beginning to learn a little.
I was very excited by the N-Bit Math routines, since it should allow high precision to be carried through all the computations. I am especially interested in the MATH_DIV w/ Remainder routine. I've had a problem with some of my projects where I need to divide two large numbers, yet retain the precision.
I was hopeful that the N_BIT Math will allow that.
I've spent many hours now trying to implement this in my chip, but have been unable to get meaningful output.
I developed this simple test program to try to understand it (unsuccessfully):
Code:
' TROUBLESHOOTER for N-BIT MATH
' By WOZZY
' PIC18F4680
' Compile with -n -ampasmwin Build Options
' 32 BIT LONG
INCLUDE "N-Bit_Math.pbp" ' Include Alexander Avtanski's Multibyte Arithmetic
' Assembly Library Wrapped for PBP by Darryl Taylor
' Version:1.3 Beta (1/7/2010)
DEFINE OSC 20 ' 20 MHz Crystal Oscillator
DEFINE DEBUG_REG PORTC ' PORT C6
DEFINE DEBUG_BIT 6 ' PORT C6
DEFINE DEBUG_BAUD 57600 ' BAUD 57600
DEFINE DEBUG_MODE 0 ' 1 = inverted, 0 = true
PRECISION CON 8 SYSTEM ' 8 bytes = 64-bit
I VAR BYTE
AA_LONG VAR LONG
BB_LONG VAR LONG
CC_LONG VAR LONG
DD_LONG VAR LONG
AA64 VAR BYTE[PRECISION]
BB64 VAR BYTE[PRECISION]
CC64 VAR BYTE[PRECISION]
DD64 VAR BYTE[PRECISION]
XX64 VAR BYTE[PRECISION]
YY64 VAR BYTE[PRECISION]
ZZ64 VAR BYTE[PRECISION]
PAUSE 500 : DEBUG " ",10,13,10,13 : PAUSE 500
MAIN:
AA_LONG = 2134567891
BB_LONG = 1987654321
CC_LONG = 2176437299
DD_LONG = 12
@ MOVE?LP _AA_LONG, _AA64 ; @ MOVE?LP _Lin, _Pout ; copy a LONG to a Pvar (PBPL only)
@ MOVE?LP _BB_LONG, _BB64 ; @ MOVE?LP _Lin, _Pout ; copy a LONG to a Pvar (PBPL only)
@ MOVE?LP _CC_LONG, _CC64 ; @ MOVE?LP _Lin, _Pout ; copy a LONG to a Pvar (PBPL only)
@ MOVE?LP _DD_LONG, _DD64 ; @ MOVE?LP _Lin, _Pout ; copy a LONG to a Pvar (PBPL only)
@ MATH_MUL _AA64, _BB64, _XX64 ; @ MATH_MUL _A, _B, _Res ; Res = A / B - Remainder in REG_Z
@ MATH_DIV _CC64, _DD64, _YY64 ; @ MATH_DIV _A, _B, _Res ; Res = A / B - Remainder in REG_Z
@ MATH_DIV _DD64, _CC64, _ZZ64 ; @ MATH_DIV _A, _B, _Res ; Res = A / B - Remainder in REG_Z
DEBUG "BYTE ORDER BYTE[7],BYTE[6],BYTE[5],BYTE[4],BYTE[3],BYTE[2],BYTE[1],BYTE[0]",10,13,10,13
DEBUG "AA64 = " : FOR I = 7 to 0 Step -1 : DEBUG BIN8 AA64[I] : NEXT I : DEBUG 10,13
DEBUG "BB64 = " : FOR I = 7 to 0 Step -1 : DEBUG BIN8 BB64[I] : NEXT I : DEBUG 10,13
DEBUG "CC64 = " : FOR I = 7 to 0 Step -1 : DEBUG BIN8 CC64[I] : NEXT I : DEBUG 10,13
DEBUG "DD64 = " : FOR I = 7 to 0 Step -1 : DEBUG BIN8 DD64[I] : NEXT I : DEBUG 10,13
DEBUG "XX64 = " : FOR I = 7 to 0 Step -1 : DEBUG BIN8 XX64[I] : NEXT I : DEBUG 10,13
DEBUG "YY64 = " : FOR I = 7 to 0 Step -1 : DEBUG BIN8 YY64[I] : NEXT I : DEBUG 10,13
DEBUG "ZZ64 = " : FOR I = 7 to 0 Step -1 : DEBUG BIN8 ZZ64[I] : NEXT I : DEBUG 10,13
DEBUG "REG_Z = " : FOR I = 7 to 0 Step -1 : DEBUG BIN8 REG_Z[I] : NEXT I : DEBUG 10,13
DEBUG 10,13,10,13,10,13,10,13
PAUSE 10000
GOTO MAIN
END
Here is the commented output:
Code:
BYTE ORDER BYTE[7],BYTE[6],BYTE[5],BYTE[4],BYTE[3],BYTE[2],BYTE[1],BYTE[0]
AA64 = 0000000000000000000000000000000001111111001110101110101111010011
= 12 OK, Should Be 2134567891: (MOVE?LP)
BB64 = 0000000000000000000000000000000001110110011110010011001010110001
= 1987654321 OK, Should Be: 1987654321 (MOVE?LP)
CC64 = 0000000000000000000000000000000010000001101110011100110000110011
= 2176437299 OK, Should Be: 2176437299 (MOVE?LP)
DD64 = 0000000000000000000000000000000000000000000000000000000000001100
=12 OK, Should Be 12: (MOVE?LP)
XX64 = 0111010100000000000000000100110000000000000000000000000000000000
= 8,430,738,828,855,080,000 Should Be: 4,242,783,092,014,010,000 (MATH-MUL)
YY64 = 0000000001000000000000000000000000000000000000000000000000000000
= 18,014,398,509,482,000 Should Be: 181,369,774 (MATH_DIV)
ZZ64 = 0000000001001100000000000000000000000000000000000000000000000000
= 21,392,098,230,009,900 Should Be: 0 (MATH_DIV)
REG_Z = 0000000000000000010011000000000000000000000000000000000000000000
= 83,562,883,710,976 Should Be: 0.0000000055135978 (Remainder)
So I was wondering if anyone has successfully implemented the Multiplication and Division in N_BIT Math.
I would really appreciate it if someone could help me decode the output, point out the error in my ways, or at least point me in the right direction.
Thanks,
Wozzy-2010
PS. Darryl, A huge thank you for all the routines you have developed.
Your Inst_Interrupts are better than sardines on toast.
High Resolution Timer with N-BITS Precision.
Darrel,
Well, Me being Me I want it to do EVERYTHING, so the distance between the gates will be an input variable.
My light source is a beam-split 650nm (red) solid state laser that's way more powerful than it needs to be (but also a lot more fun!)
My Optical sensors are Osram SFH 5840 PhotoTransistors with built-in Schmitt Trigger.
The outputs are combined into a single pulse using an LS74F00 configured as an S-R Latch. (this allows me to use the same code and input pin with either one or two sensors)
The timer code is based on DT_INSTANT_INTERRUPTS running on a PIC18F4680 @ 20 MHz
This is all working very well as a high resolution timer, though I am still working on some corrections for software and hardware delays.
I may consider redoing the timer portion of the software using the N-Bit Variable Math, as I'm currently limited to about 1.5 Minutes.
I needed the N-Bit Math to get the resolution I want when converting from Time to Speed, as I end up dividing two large numbers.
My immediate goals are...
How fast are Pinewood Derby Cars?
How fast is my dog? (Very Fast!)
How fast am I? (Very Slow)
How fast can I back-slap someone? (approx. 29.97235 MPH)-DONE!
What is the muzzle velocity of my air rifle with different pellets?
How fast does that Jerk down the street drive past my house while kids are outside playing?
...
I only have time to work on this late at night.
I'll work on cleaning the code up a little before I lay it out for all to see.
So far this has been a really fun and educational project.
My youngest daughter (11yo) is learning with me, she seems very interested in what I'm doing. So I try and explain it to her as I go.
Again thanks to you and the others on the Forum that are so willing to share your knowledge to help others learn.
How do you display large numbers in decimal format instead of binary?
Not being the brightest bulb in the math department, I was trying to figure out how to display the value of 100000 in decimal format on the debug screen.
So if I have the following loaded into a PVAR called SetPoint
SetPoint[0] = 160
SetPoint[1] = 134
SetPoint[2] = 1
SetPoint[3] = 0
How can I display is as 100000 as opposed to:
00000000000000011000011010100000
Hoping someone can point me in the right direction.
Eric
put 100000 into a PRECISION variable. Using a calculator I found the binary equivalent of 100000 and then took each byte and calculated the decimal value of it and plugged it in as shown below. Obviously this is quite laborious
PRECISION CON 4 SYSTEM
include "NBit_Math.bas"
SetPoint VAR BYTE[PRECISION]
SetPoint[0] = 160
SetPoint[1] = 134
SetPoint[2] = 1
SetPoint[3] = 0
N-bit_Math strange behavior
Hi!
I have been away from PIC and PICbasic world over one and a half year now. However, I'm back again and run to a really strange thing. I have slightly over 28 k code where I need 36 bits for calculations, so I found that wonderful N-bit_Math (just beautiful). There is however, something strange going on.
the code for N-bits is as suggested by Darrel. And compiles without errors and warnings, as long as .... here is the code:
Code:
PRECISION CON 5 SYSTEM ' 5*8 = 40 bits, byte size for registers
include "N-Bit_Math.pbp"
define OSC 48 ' used clock frequenze
SetPoint VAR BYTE[PRECISION]
Position VAR BYTE[PRECISION]
Error VAR BYTE[PRECISION]
Current VAR BYTE[PRECISION]
MyVar VAR BYTE[PRECISION]
by var byte
wo var word
LHi var word
LMi var word
LLo var word
LHi = $7: LMi = $2174: LLo = $6FD9
for by = 0 to 4
select case by
case 0,1 : wo = LLo
case 2,3 : wo = LMi
case 4 : wo = LHi
end select
' SetPoint[2] = wo & $FF 'A
if (by & 1) = 0 _
then
by= by ' SetPoint[by] = wo & $FF ' B
else
by=by ' SetPoint[by] = wo >> 8 ' C
endif
next by
@ MATH_DIV _SetPoint, _Position, _Error
There are three comments (A,B and C). Depending on what combination you have will give different results for the compilation. As it is "now", SetPoint not involved, it compiles OK.
If I enable A then there are two warnings one saying both in the .mac file and ..pbppic18.lib file that "Address exceeds maximum range for this processor".
If I enable B and/or C without A then there is one Error (126) in pbppic18.lib saying "argument out of range (32816 not between 0-32767) and bunch of warnings, all saying "Address exceeds maximum range for this processor" in .lib and .mac files.
If I copy that to a new file and compile it then there are no problems to compile it.
I have been looking around the rest of the code to found something strange but can not image what it would be.
I'm using PicBasic pro 2.50b, MPASM and target is 18F4550.
The real question is:
What can in a code (the rest of it), what could make the compiler to act like that. Any ideas ?
Any suggestion what to look for? Please help....