Floating Point Co-Processor weirdness and other issues
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