Shop OBEX P1 Docs P2 Docs Learn Events
Floating Point Co-Processor weirdness and other issues — Parallax Forums

Floating Point Co-Processor weirdness and other issues

FireFire Posts: 4
edited 2006-07-14 14:56 in BASIC Stamp
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.

'-------------------- 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

  • FireFire Posts: 4
    edited 2006-07-07 15:10
    Anyone? Is this in the wrong forum?
  • Ryan ClarkeRyan Clarke Posts: 738
    edited 2006-07-07 15:45
    You need to post complete code. Where is the PRINT_LONG subroutine? Directives? What FPU are you using? The rest of the constant/variable declarations?

    Ryan

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Ryan Clarke
    Parallax Tech Support

    RClarke@Parallax.com

    Post Edited (Ryan Clarke (Parallax)) : 7/7/2006 3:51:43 PM GMT
  • FireFire Posts: 4
    edited 2006-07-07 18:03
    Ryan Clarke (Parallax) said...
    You need to post complete code. Where is the PRINT_LONG subroutine? Directives? What FPU are you using? The rest of the constant/variable declarations?

    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
  • camtcamt Posts: 45
    edited 2006-07-14 14:38
    Fire,

    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
  • FireFire Posts: 4
    edited 2006-07-14 14:56
    Thank you Cam! You are a life-saver. I have now set 7 digits as the maximum, and I'm getting (near) flawless results on my operations.

    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
Sign In or Register to comment.