Floating Point Co-Processor weirdness and other issues
Fire
Posts: 4
Hey all,
I've recently begun programming using the Basic Stamp Homework board (using the on-board BS2). I've hooked up a MicroMega uM-FPU (v2) using SPI (I've verified the connections). I'm using the FPU IDE; that spares me a lot of headache!
What I'm trying to do:
I'm sending two 8-digit numbers into two separate FPU registers. This seems to work without problems. I've shown one of the numbers below. The other number is pretty much identical.
Now, I wanted to verify that the number stored in the FPU register is accurate.
It is not! Here is the output shown in the debug screen:
I get this discrepancy no matter what combination of digits I put in. However, I don't seem to have problems if the number is 6 digits or lower. I have a feeling I'm not capturing the number properly on the read FROM the FPU. I'm allocating it as a "long", which should allocate it 32 bits. An 8-digit number is only 27 bits or so. There cannot be an error of 5 bits!
What am I doing wrong?
Any help would be much appreciated. Thanks in advance!
Edit: I've uploaded the entire program as an attachment. Additionally, here is the complete code, including the snippets shown above:
COMPLETE CODE
Post Edited (Fire) : 7/9/2006 9:17:05 PM GMT
I've recently begun programming using the Basic Stamp Homework board (using the on-board BS2). I've hooked up a MicroMega uM-FPU (v2) using SPI (I've verified the connections). I'm using the FPU IDE; that spares me a lot of headache!
What I'm trying to do:
I'm sending two 8-digit numbers into two separate FPU registers. This seems to work without problems. I've shown one of the numbers below. The other number is pretty much identical.
'-------------------- uM-FPU V2 Register Definitions -------------------------- firstNum CON 1 ' uM-FPU register 1 secondNum CON 2 ' uM-FPU register 2 '-------------------- Variable Definitions --------------------------- readNum VAR Byte(4) ' unsigned long variable f VAR Byte(8) ' signed byte variable f(7)=5 ' This artificial setup is for testing purposes only f(6)=7 ' In reality, an FPGA will provide the serial input f(5)=2 ' This serial input will be processed below (not shown here) f(4)=8 f(3)=1 f(2)=4 f(1)=3 f(0)=8 '--- firstNum = (((f(4) + (f(5)*10) + (f(6)*100) + (f(7)*1000))*100)*100) + ((f(0)) + (f(1)*10) + (f(2)*100) + (f(3)*1000)) SHIFTOUT FpuOut, FpuClk, MSBFIRST, [noparse][[/noparse]firstNum, XOP, LEFT, XOP, LEFT, XOP, LEFT, LOADBYTE, f(4), FSET, XOP, LEFT, LOADBYTE, f(5), FSET, FWRITEB, $41, $20, $00, $00, FMUL, XOP, RIGHT, FADD, XOP, LEFT, LOADBYTE, f(6), FSET] GOSUB Fpu_Wait SHIFTOUT FpuOut, FpuClk, MSBFIRST, [noparse][[/noparse]FWRITEB, $42, $C8, $00, $00, FMUL, XOP, RIGHT, FADD, XOP, LEFT, LOADBYTE, f(7), FSET, FWRITEB, $44, $7A, $00, $00, FMUL, XOP, RIGHT, FADD, XOP, RIGHT, FSET, FWRITEB, $42, $C8, $00, $00, FMUL] GOSUB Fpu_Wait SHIFTOUT FpuOut, FpuClk, MSBFIRST, [noparse][[/noparse]XOP, RIGHT, FSET, FWRITEB, $42, $C8, $00, $00, FMUL, XOP, RIGHT, FSET, XOP, LEFT, XOP, LEFT, LOADBYTE, f(0), FSET, XOP, RIGHT, FSET, XOP, LEFT, LOADBYTE, f(1), FSET, FWRITEB, $41, $20, $00, $00] GOSUB Fpu_Wait SHIFTOUT FpuOut, FpuClk, MSBFIRST, [noparse][[/noparse]FMUL, XOP, RIGHT, FADD, XOP, LEFT, LOADBYTE, f(2), FSET, FWRITEB, $42, $C8, $00, $00, FMUL, XOP, RIGHT, FADD, XOP, LEFT, LOADBYTE, f(3), FSET, FWRITEB, $44, $7A, $00, $00, FMUL, XOP, RIGHT, FADD] GOSUB Fpu_Wait SHIFTOUT FpuOut, FpuClk, MSBFIRST, [noparse][[/noparse]XOP, RIGHT, FADD] '--- readNum = firstNum SHIFTOUT FpuOut, FpuClk, MSBFIRST, [noparse][[/noparse]firstNum, FIX, SELECTA] GOSUB Fpu_Wait SHIFTOUT FpuOut, FpuClk, MSBFIRST, [noparse][[/noparse]XOP, LREAD] SHIFTIN FpuIn, FpuClk, MSBPRE, [noparse][[/noparse]readNum(3), readNum(2), readNum(1), readNum(0)] '--- '
Now, I wanted to verify that the number stored in the FPU register is accurate.
DEBUG "Firstnum should be : ",DEC f(4) + (f(5)*10) + (f(6)*100) + (f(7)*1000),DEC (f(0) + (f(1)*10) + (f(2)*100) + (f(3)*1000)),CR DEBUG "FPU says it is : " GOSUB PRINT_LONG DEBUG CR
It is not! Here is the output shown in the debug screen:
Firstnum should be : 57281438 FPU says it is : 57281436
I get this discrepancy no matter what combination of digits I put in. However, I don't seem to have problems if the number is 6 digits or lower. I have a feeling I'm not capturing the number properly on the read FROM the FPU. I'm allocating it as a "long", which should allocate it 32 bits. An 8-digit number is only 27 bits or so. There cannot be an error of 5 bits!
What am I doing wrong?
Any help would be much appreciated. Thanks in advance!
Edit: I've uploaded the entire program as an attachment. Additionally, here is the complete code, including the snippets shown above:
COMPLETE CODE
'============================================================================== ' Copyright © Micromega Corporation 2002-2005. All rights reserved ' ' @file umfpu-spi.bs2 ' @target Basic Stamp ' ' This file contains a program template that provides all of the definitions ' and support code for using the uM-FPU floating point coprocessor with the ' BASIC Stamp over an SPI inerface. It can be used as a template for new ' programs, or the necessary parts can be copied to an existing program. ' Unused support routines can be deleted to save space, but it is recommended ' that the uM-FPU definitions be copied as a complete block. In order to reduce ' memory requirements, some routines fall through to the code that follows it. ' All of these cases are clearly commented. When deleting unused routines, or ' copying routines to another program be sure to check the comments. ' ' @author Cam Thompson, Micromega Corporation ' @version V2.0 - January 8, 2005 ' @changes ' V2.1 - May 11, 2005 ' - WRITEA, WRITEB changed to FWRITEA, FWRITEB ' - updated for BS2PX ' V2.0 - January 8, 2005 ' - modified for uM-FPU V2.0 ' V1.0 - April 29, 2004 ' - original version ' '{$STAMP BS2} '{$PBASIC 2.5} '============================================================================== '============================================================================== '-------------------- uM-FPU definitions (V2.1) ------------------------------- '============================================================================== FpuClk PIN 15 ' SPI clock (connects to SCLK/SCL) FpuOut PIN 14 ' SPI data out (connects to SIN/SDA) FpuIn PIN 14 ' SPI data in (connects to SOUT) #IF ($STAMP = BS2SX) OR ($STAMP = BS2P) OR ($STAMP = BS2PX) #THEN ResetTime CON 625 ' 500 usec reset pulse #ELSE ResetTime CON 250 ' 500 usec reset pulse #ENDIF '-------------------- uM-FPU opcodes ------------------------------------------ SELECTA CON $00 ' select A register SELECTB CON $10 ' select B register FWRITEA CON $20 ' select A and write float to register FWRITEB CON $30 ' select B and write float to register FREAD CON $40 ' read float from register FSET CON $50 ' A = REG LSET CON $50 ' A = REG FADD CON $60 ' A = A + REG (float) FSUB CON $70 ' A = A - REG (float) FMUL CON $80 ' A = A * REG (float) FDIV CON $90 ' A = A / REG (float) LADD CON $A0 ' A = A + REG (long) LSUB CON $B0 ' A = A - REG (long) LMUL CON $C0 ' A = A * REG (long) LDIV CON $D0 ' A = A / REG (long) SQRT CON $E0 ' A = sqrt(A) LOG CON $E1 ' A = ln(A) LOG10 CON $E2 ' A = log(A) EXP CON $E3 ' A = e ** A EXP10 CON $E4 ' A = 10 ** A FSIN CON $E5 ' A = sin(A) radians FCOS CON $E6 ' A = cos(A) radians FTAN CON $E7 ' A = tan(A) radians FLOOR CON $E8 ' A = nearest integer <= A CEIL CON $E9 ' A = nearest integer >= A ROUND CON $EA ' A = nearest integer to A NEGATE CON $EB ' A = -A FABS CON $EC ' A = |A| INVERSE CON $ED ' A = 1 / A DEGREES CON $EE ' A = A / (PI / 180) radians to degrees RADIANS CON $EF ' A = A * (PI / 180) degreees to radians SYNC CON $F0 ' synchronization FLOAT CON $F1 ' copy A to register 0 and float FIX CON $F2 ' copy A to register 0 and fix FCOMPARE CON $F3 ' compare A and B LOADBYTE CON $F4 ' write signed byte to register 0, convert to float LOADUBYTE CON $F5 ' write unsigned byte to register 0, convert to float LOADWORD CON $F6 ' write signed word to register 0, convert to float LOADUWORD CON $F7 ' write unsigned word to register 0, convert to float READSTR CON $F8 ' read zero terminated string ATOF CON $F9 ' convert ASCII to float, store in A FTOA CON $FA ' convert float to ASCII ATOL CON $FB ' convert ASCII to long, store in A LTOA CON $FC ' convert long to ASCII FSTATUS CON $FD ' get the status of A register XOP CON $FE ' extended opcode NOP CON $FF ' nop FUNCTION CON $00 ' (XOP) user functions 0-15 READBYTE CON $90 ' (XOP) read low 8 bits of A (long) READWORD CON $91 ' (XOP) read low 16 bits of A (long) READLONG CON $92 ' (XOP) read 32-bit long value from A READFLOAT CON $93 ' (XOP) read floating point value from A LINCA CON $94 ' (XOP) A = A + 1 (long) LINCB CON $95 ' (XOP) A = A + 1 (long) LDECA CON $96 ' (XOP) A = A - 1 (long) LDECB CON $97 ' (XOP) A = A - 1 (long) LAND CON $98 ' (XOP) A = A AND B (long) LOR CON $99 ' (XOP) A = A OR B (long) LXOR CON $9A ' (XOP) A = A XOR B (long) LNOT CON $9B ' (XOP) A = NOT A (long) LTST CON $9C ' (XOP) status of A AND B (long) LSHIFT CON $9D ' (XOP) shift A by B bits (long) LWRITEA CON $A0 ' (XOP) select A and write long to register LWRITEB CON $B0 ' (XOP) select B and write long to register LREAD CON $C0 ' (XOP) read 32-bit long from register LUDIV CON $D0 ' (XOP) A = A / REG (unsigned long) POWER CON $E0 ' (XOP) A = A ** B ROOT CON $E1 ' (XOP) A = the Bth root of A FMIN CON $E2 ' (XOP) A = minimum of A and B FMAX CON $E3 ' (XOP) A = maximum of A and B FRACTION CON $E4 ' (XOP) load register 0 with the fractional part of A ASIN CON $E5 ' (XOP) A = asin(A) radians ACOS CON $E6 ' (XOP) A = acos(A) radians ATAN CON $E7 ' (XOP) A = atan(A) radians ATAN2 CON $E8 ' (XOP) A = atan(A/B) LCOMPARE CON $E9 ' (XOP) long compare A and B LUCOMPARE CON $EA ' (XOP) unsigned long compare A and B LSTATUS CON $EB ' (XOP) long status LNEGATE CON $EC ' (XOP) A = -A (long) LABS CON $ED ' (XOP) A = |A| (long) LEFT CON $EE ' (XOP) right parenthesis RIGHT CON $EF ' (XOP) left parenthesis LOADZERO CON $F0 ' (XOP) load register 0 with zero LOADONE CON $F1 ' (XOP) load register 0 with 1.0 LOADE CON $F2 ' (XOP) load register 0 with e LOADPI CON $F3 ' (XOP) load register 0 with pi LONGBYTE CON $F4 ' (XOP) write signed byte to register 0, convert to long LONGUBYTE CON $F5 ' (XOP) write unsigned byte to register 0, convert to long LONGWORD CON $F6 ' (XOP) write signed word to register 0, convert to long LONGUWORD CON $F7 ' (XOP) write unsigned word to register 0, convert to long IEEEMODE CON $F8 ' (XOP) set IEEE mode (default) PICMODE CON $F9 ' (XOP) set PIC mode CHECKSUM CON $FA ' (XOP) calculate code checksum BREAK CON $FB ' (XOP) debug breakpoint TRACEOFF CON $FC ' (XOP) turn debug trace off TRACEON CON $FD ' (XOP) turn debug trace on TRACESTR CON $FE ' (XOP) send debug string to trace buffer VERSION CON $FF ' (XOP) get version string SyncChar CON $5C ' sync character '-------------------- uM-FPU variables ---------------------------------------- dataWord VAR Word ' data word dataHigh VAR dataWord.HIGHBYTE ' high byte of dataWord dataLow VAR dataword.LOWBYTE ' low byte of dataLow dataByte VAR dataLow ' (alternate name) opcode VAR dataHigh ' opcode (same as dataHigh) reg VAR dataHigh ' register (same as dataHigh) format VAR dataLow ' format (same as dataLow) status VAR dataLow ' status (same as dataLow) status_Zero VAR status.BIT0 ' Zero status bit (0-not zero, 1-zero) status_Sign VAR status.BIT1 ' Sign status bit (0-positive, 1-negative) status_NaN VAR status.BIT2 ' Not a Number status bit (0-valid number, 1-NaN) status_Inf VAR status.BIT3 ' Infinity status bit (0-not infinite, 1-infinite) '==================== end of uM-FPU definitions =============================== '============================================================================== '==================== main definitions ======================================== '============================================================================== '============================================================================== '-------------------- initialization ------------------------------------------ '============================================================================== Reset: 'FPU_Reset must be called at the start of the program to establish 'proper communications with the uM-FPU. The following example displays a 'message if the reset fails. If the reset is successful, the uM-FPU version 'string is displayed. GOSUB Fpu_Reset ' reset the FPU hardware IF status <> SyncChar THEN DEBUG "uM-FPU not detected." END ELSE GOSUB Print_Version ' display the uM-FPU version number DEBUG " - Detected and Initialized successfully.",CR ENDIF ' (Your initialization code would be inserted here.) '============================================================================== '-------------------- main routine -------------------------------------------- '============================================================================== Main: ' Coded for ESE 499/440/441 ' Version 0.25 7-5-2006 ' Changes: ' Version 0.26 - Added LCD display ' Version 0.25 - Added Start button on Pin 0 ' Version 0.2 - Added FPU functionality baudRate CON 16468 ' Define the Baud Rate coming from FPGA here 'f VAR Byte(8) ' First number being serially input (temporary catcher) 's VAR Byte(8) ' Second number being serially input (temporary catcher) LCDpin CON 10 ' What pin is the LCD connected to? BaudLCD CON 32 ' What is the Baud rate of the LCD? inCount VAR Byte ' This counter will be used in loops for serial input '-------------------- uM-FPU V2 Register Definitions -------------------------- firstNum CON 1 ' uM-FPU register 1 secondNum CON 2 ' uM-FPU register 2 '-------------------- Variable Definitions --------------------------- readNum VAR Byte(4) ' unsigned long variable f VAR Byte(8) ' signed byte variable s VAR Byte(8) ' signed byte variable HIGH LCDpin ' LCD initialization PAUSE 100 SEROUT LCDpin, BaudLCD, [noparse][[/noparse]18, 12] ' Clear LCD PAUSE 50 f(7)=5 ' This artificial setup is for testing purposes only f(6)=7 ' In reality, the FPGA will provide the serial input f(5)=2 ' This serial input will be processed in the f(4)=8 ' disabled lines below f(3)=1 f(2)=4 f(1)=3 f(0)=8 s(7)=9 s(6)=6 s(5)=5 s(4)=7 s(3)=3 s(2)=9 s(1)=1 s(0)=4 INPUT 0 ' Setting pin0 as an input pin to start operation DEBUG "Push start to begin.",CR SEROUT LCDpin, BaudLCD, [noparse][[/noparse]"Push start."] wait0: ' Program will wait here until start button is pushed IF IN0 <> 0 THEN wait0 SEROUT LCDpin, BaudLCD, [noparse][[/noparse]18, 12] ' Clear LCD PAUSE 50 'FOR inCount = 7 TO 0 STEP -1 ' Capture sequence captures in reverse order ' SERIN 1, baudRate, f(inCount) ' so that recombination is easier below ' DEBUG "Incoming : ",f(inCount) ' This is the capture of the first number 'NEXT 'FOR inCount = 7 TO 0 STEP -1 ' This is the capture of the second number ' SERIN 1, baudRate, s(inCount) ' DEBUG "Incoming2 : ",s(inCount) 'NEXT '--- firstNum = (((f(4) + (f(5)*10) + (f(6)*100) + (f(7)*1000))*100)*100) + ((f(0)) + (f(1)*10) + (f(2)*100) + (f(3)*1000)) SHIFTOUT FpuOut, FpuClk, MSBFIRST, [noparse][[/noparse]firstNum, XOP, LEFT, XOP, LEFT, XOP, LEFT, LOADBYTE, f(4), FSET, XOP, LEFT, LOADBYTE, f(5), FSET, FWRITEB, $41, $20, $00, $00, FMUL, XOP, RIGHT, FADD, XOP, LEFT, LOADBYTE, f(6), FSET] GOSUB Fpu_Wait SHIFTOUT FpuOut, FpuClk, MSBFIRST, [noparse][[/noparse]FWRITEB, $42, $C8, $00, $00, FMUL, XOP, RIGHT, FADD, XOP, LEFT, LOADBYTE, f(7), FSET, FWRITEB, $44, $7A, $00, $00, FMUL, XOP, RIGHT, FADD, XOP, RIGHT, FSET, FWRITEB, $42, $C8, $00, $00, FMUL] GOSUB Fpu_Wait SHIFTOUT FpuOut, FpuClk, MSBFIRST, [noparse][[/noparse]XOP, RIGHT, FSET, FWRITEB, $42, $C8, $00, $00, FMUL, XOP, RIGHT, FSET, XOP, LEFT, XOP, LEFT, LOADBYTE, f(0), FSET, XOP, RIGHT, FSET, XOP, LEFT, LOADBYTE, f(1), FSET, FWRITEB, $41, $20, $00, $00] GOSUB Fpu_Wait SHIFTOUT FpuOut, FpuClk, MSBFIRST, [noparse][[/noparse]FMUL, XOP, RIGHT, FADD, XOP, LEFT, LOADBYTE, f(2), FSET, FWRITEB, $42, $C8, $00, $00, FMUL, XOP, RIGHT, FADD, XOP, LEFT, LOADBYTE, f(3), FSET, FWRITEB, $44, $7A, $00, $00, FMUL, XOP, RIGHT, FADD] GOSUB Fpu_Wait SHIFTOUT FpuOut, FpuClk, MSBFIRST, [noparse][[/noparse]XOP, RIGHT, FADD] '--- readNum = firstNum SHIFTOUT FpuOut, FpuClk, MSBFIRST, [noparse][[/noparse]firstNum, FIX, SELECTA] GOSUB Fpu_Wait SHIFTOUT FpuOut, FpuClk, MSBFIRST, [noparse][[/noparse]XOP, LREAD] SHIFTIN FpuIn, FpuClk, MSBPRE, [noparse][[/noparse]readNum(3), readNum(2), readNum(1), readNum(0)] '--- ' DEBUG "Firstnum should be : ",DEC f(4) + (f(5)*10) + (f(6)*100) + (f(7)*1000),DEC (f(0) + (f(1)*10) + (f(2)*100) + (f(3)*1000)),CR DEBUG "FPU says it is : " GOSUB PRINT_LONG DEBUG CR DEBUG "1st: ",DEC readNum(3),DEC readNum(2),DEC readNum(1),DEC readNum(0),CR SEROUT LCDpin, BaudLCD, [noparse][[/noparse]"1st: ",DEC readNum(3),DEC readNum(2),DEC readNum(1),DEC readNum(0),CR] '--- secondNum = (((s(4) + (s(5)*10) + (s(6)*100) + (s(7)*1000))*100)*100) + ((s(0)) + (s(1)*10) + (s(2)*100) + (s(3)*1000)) SHIFTOUT FpuOut, FpuClk, MSBFIRST, [noparse][[/noparse]secondNum, XOP, LEFT, XOP, LEFT, XOP, LEFT, LOADBYTE, s(4), FSET, XOP, LEFT, LOADBYTE, s(5), FSET, FWRITEB, $41, $20, $00, $00, FMUL, XOP, RIGHT, FADD, XOP, LEFT, LOADBYTE, s(6), FSET] GOSUB Fpu_Wait SHIFTOUT FpuOut, FpuClk, MSBFIRST, [noparse][[/noparse]FWRITEB, $42, $C8, $00, $00, FMUL, XOP, RIGHT, FADD, XOP, LEFT, LOADBYTE, s(7), FSET, FWRITEB, $44, $7A, $00, $00, FMUL, XOP, RIGHT, FADD, XOP, RIGHT, FSET, FWRITEB, $42, $C8, $00, $00, FMUL] GOSUB Fpu_Wait SHIFTOUT FpuOut, FpuClk, MSBFIRST, [noparse][[/noparse]XOP, RIGHT, FSET, FWRITEB, $42, $C8, $00, $00, FMUL, XOP, RIGHT, FSET, XOP, LEFT, XOP, LEFT, LOADBYTE, s(0), FSET, XOP, RIGHT, FSET, XOP, LEFT, LOADBYTE, s(1), FSET, FWRITEB, $41, $20, $00, $00] GOSUB Fpu_Wait SHIFTOUT FpuOut, FpuClk, MSBFIRST, [noparse][[/noparse]FMUL, XOP, RIGHT, FADD, XOP, LEFT, LOADBYTE, s(2), FSET, FWRITEB, $42, $C8, $00, $00, FMUL, XOP, RIGHT, FADD, XOP, LEFT, LOADBYTE, s(3), FSET, FWRITEB, $44, $7A, $00, $00, FMUL, XOP, RIGHT, FADD] GOSUB Fpu_Wait SHIFTOUT FpuOut, FpuClk, MSBFIRST, [noparse][[/noparse]XOP, RIGHT, FADD] '--- readNum = secondNum SHIFTOUT FpuOut, FpuClk, MSBFIRST, [noparse][[/noparse]secondNum, FIX, SELECTA] GOSUB Fpu_Wait SHIFTOUT FpuOut, FpuClk, MSBFIRST, [noparse][[/noparse]XOP, READLONG] SHIFTIN FpuIn, FpuClk, MSBPRE, [noparse][[/noparse]readNum(3), readNum(2), readNum(1), readNum(0)] DEBUG "Secondnum should be : ",DEC s(4) + (s(5)*10) + (s(6)*100) + (s(7)*1000),DEC (s(0) + (s(1)*10) + (s(2)*100) + (s(3)*1000)),CR DEBUG "FPU says it is : " GOSUB PRINT_LONG DEBUG CR END '============================================================================== '-------------------- uM-FPU SPI support routines (V2.1) ---------------------- '============================================================================== Fpu_Reset: LOW FpuClk ' set clock and data lines Low LOW FpuOut PULSOUT FpuClk, ResetTime ' send reset pulse to uM-FPU PAUSE 8 ' check for synchronization SHIFTOUT FpuOut, FpuClk, MSBFIRST, [noparse][[/noparse]SYNC] SHIFTIN FpuIn, FpuClk, MSBPRE, [noparse][[/noparse]status] RETURN Fpu_Wait: INPUT FpuIn ' (required for 2-wire interface) Fpu_Wait2: IF (FpuIn = 1) THEN GOTO Fpu_Wait2 ' wait until uM-FPU is ready RETURN Print_Version: ' get the uM-FPU version string SHIFTOUT FpuOut, FpuClk, MSBFIRST, [noparse][[/noparse]XOP, VERSION] GOTO Print_String2 ' print it Print_Float: format = 0 ' set format to zero (free format) ' (fall through to Print_FloatFormat) Print_FloatFormat: opcode = FTOA ' convert floating point to formatted ASCII GOTO Print_String ' print the value Print_Long: format = 0 ' set format to 0 (free format) ' (fall through to Print_LongFormat) Print_LongFormat: opcode = LTOA ' convert long integer to formatted ASCII ' (fall through to Print_String) Print_String: ' send conversion command SHIFTOUT FpuOut, FpuClk, MSBFIRST, [noparse][[/noparse]opcode, format] Print_String2: GOSUB Fpu_Wait ' wait until uM-FPU is ready SHIFTOUT FpuOut, FpuClk, MSBFIRST, [noparse][[/noparse]READSTR] DO ' display zero terminated string SHIFTIN FpuIn, FpuClk, MSBPRE, [noparse][[/noparse]dataByte] IF (dataByte = 0 OR dataByte > 127) THEN EXIT DEBUG dataByte LOOP RETURN '==================== end of uM-FPU SPI support routines ======================
Post Edited (Fire) : 7/9/2006 9:17:05 PM GMT
Comments
Ryan
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Ryan Clarke
Parallax Tech Support
RClarke@Parallax.com
Post Edited (Ryan Clarke (Parallax)) : 7/7/2006 3:51:43 PM GMT
Sorry, I wanted to keep the post simple. I've uploaded the complete .bs2 file as an attachment to my first post, and I've posted the complete code as well.
I am using the MicroMega uM-FPU v2.
Post Edited (Fire) : 7/7/2006 6:10:18 PM GMT
There is nothing wrong with your code, or the uM-FPU, you are just exceeding the resolution of a 32-bit floating point number. A 32-bit FP number is stored as a sign bit, an 8 bit exponent, and a 23-bit mantissa. The mantissa can actually store a 24-bit normalized number, so the largest integer value that you can store and retrieve unmodified is (2^24)-1, or 16,777,215. In your test you use 57,281,438 which exceeds the precision of a 32-bit FP number. If you tried the same test with 7 or fewer digits, you would always get the same value. The number of significant digits in a 32-bit FP number is slightly more than 7 digits.
A little more background: a normalized 32-bit FP number can store values as large as 10^(+38.53) or as small as 10^(-38.53) . That's a very large range, but to cover this range the floating point format has to adjust the exponent and mantissa fields to fit in 32 bits. Something has to give, and it's precision. In most cases this isn't an issue because the number of significant digits is more important then the total number of digits. In otherwords, a number may be large, but still only have 7 or fewer significant digits.
If you want to get a better feel for how floating point numbers are put together try the "uM-FPU Converter (with uM-FPU V1.0 samples)" locacted on the following page: http://www.micromegacorp.com/downloads.html.
It lets you type in decimal numbers and displays the FP number on the fly, or alternatively you can type in a hex representation of a FP number (e.g. $3F800000) and it will display the decimal equivalent.
If you have further questions, regarding the uM-FPU you can also contact support@micromegcorp.com. I'm not always on the forums.
Cam
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Cam Thompson
Micromega Corporation
I'm always getting around 0.01% error while computing with two 7-digit numbers, but this is very much acceptable. Thank you once again! [noparse]:)[/noparse]
Edit: And I think the (perceived) error is because of the bug using FTOA to display the number, which always errors out in the 8th digit.
Post Edited (Fire) : 7/14/2006 3:12:15 PM GMT