I've found also a few more problems with the [AN575] INT24 routine:
1) when AEXP==0, which means zero floating number, but AARGB0:1 is not zero, return will be incorrect. So AARGB0:1 have to be cleared in that case.
2) problem with overflow checking (for example -32769 (0x8e8001) will result in 0xC78e, instead of 0x8000)
There is really something wrong with rounding. They teach in school that if a number is in the middle between two integers, the highest by absolute value is taken. For example, MATLAB has four rounding functions:
ROUND - round to closest integer (like in school)
FIX - round towards zero (ignore fractional part)
CEIL - round towards plus infinity
FLOOR - round towards minus infinity
let x = [-1:0.25:1]
» x = [-1:0.25:1]
x =
-1 -0.75 -0.5 -0.25 0 0.25 0.5 0.75 1
» round(x)
ans =
-1 -1 -1 0 0 0 1 1 1
» fix(x)
ans =
-1 0 0 0 0 0 0 0 1
» ceil(x)
ans =
-1 0 0 0 0 1 1 1 1
» floor(x)
ans =
-1 -1 -1 -1 0 0 0 0 1
»
I assume that the INT24 routine should implement ROUND function. But why there is a check for AARGB1.0 (LSb of integer result)?...
[Here is] a fixed version (I hope) of INT24 routine (fpint.asm).
#include <p16f84.inc>
cblock 0x20
AEXP ; - exponent 2^(AEXP - 127)
AARGB0
AARGB1 ;- low byte
BEXP
BARGB0
BARGB1 ; - temporary for result
TEMPB0
TEMPB1
LOOPCOUNT ; - counter
SIGN
FPFLAGS
endc
mov macro x, y
movlw x
movwf y
endm
EXP EQU AEXP
#define _C STATUS, C
#define _Z STATUS, Z
#define EXPBIAS 0x7F
#define MSB 0x7
#define LSB 0x0
#define RND 0x0
#define SAT 0x1
#define IOV 0x2
BSF FPFLAGS, RND
BSF FPFLAGS, SAT
;9.4999 8217FF 0009 9
mov 0x82, AEXP
mov 0x17, AARGB0
mov 0xFF, AARGB1
call INT2416
nop
;9.50 821800 000A 10
mov 0x82, AEXP
mov 0x18, AARGB0
mov 0x00, AARGB1
call INT2416
nop
;9.9999 821FFF 000A 10
mov 0x82, AEXP
mov 0x1F, AARGB0
mov 0xFF, AARGB1
call INT2416
nop
;10.50 822800 000A 11
mov 0x82, AEXP
mov 0x28, AARGB0
mov 0x00, AARGB1
call INT2416
nop
;10.999 822FFF 000A 11
mov 0x82, AEXP
mov 0x2F, AARGB0
mov 0xFF, AARGB1
call INT2416
nop
;10.4999 8227FF 000A 10
mov 0x82, AEXP
mov 0x27, AARGB0
mov 0xFF, AARGB1
call INT2416
nop
;11.000 823000 000B 11
mov 0x82, AEXP
mov 0x30, AARGB0
mov 0x00, AARGB1
call INT2416
nop
;11.4999 8237FF 000B 11
mov 0x82, AEXP
mov 0x37, AARGB0
mov 0xFF, AARGB1
call INT2416
nop
;11.50 823800 000C 12
mov 0x82, AEXP
mov 0x38, AARGB0
mov 0x00, AARGB1
call INT2416
nop
;11.999 823FFF 000C 12
mov 0x82, AEXP
mov 0x3F, AARGB0
mov 0xFF, AARGB1
call INT2416
nop
;12.0 824000 000C 12
mov 0x82, AEXP
mov 0x40, AARGB0
mov 0x00, AARGB1
call INT2416
nop
;12.4999 8247FF 000C 12
mov 0x82, AEXP
mov 0x47, AARGB0
mov 0xFF, AARGB1
call INT2416
nop
;12.50 824800 000C 12
mov 0x82, AEXP
mov 0x48, AARGB0
mov 0x00, AARGB1
call INT2416
nop
;12.9999 824FFF 000C 12
mov 0x82, AEXP
mov 0x4F, AARGB0
mov 0xFF, AARGB1
call INT2416
nop
;13.0 825000 000D 13
mov 0x82, AEXP
mov 0x50, AARGB0
mov 0x00, AARGB1
call INT2416
nop
;overflow 32767.5 (RND=1, SAT=1) -> 7FFF
mov 0x8d, AEXP
mov 0x7f, AARGB0
mov 0xff, AARGB1
call INT2416
nop
;overflow -32769 (RND=1, SAT=1) -> 8000
mov 0x8e, AEXP
mov 0x80, AARGB0
mov 0x01, AARGB1
call INT2416
nop
;zero -> 0000
clrf AEXP
call INT2416
nop
;**********************************************************************************************
; Float to integer conversion
;
; Input: 24 bit floating point number in AEXP, AARGB0, AARGB1
;
; Use: CALL INT2416 or CALL INT24
;
; Output: 16 bit 2's complement integer right justified in AARGB0, AARGB1
;
; Result: AARG <-- INT( AARG ) , RND = 0
; AARG <-- ROUND( AARG ), RND = 1
;
; Max Timing: 2+7+8+9+7+7*6-1+11+2 = 87 clks RND = 0
; 2+7+8+9+7+7*6-1+4+11+2 = 91 clks RND = 1, SAT = 0
; 2+7+8+9+7+7*6-1+19+2 = 95 clks RND = 1, SAT = 1
;
; Min Timing: 2+8+2 = 14 clks
;
; PM: 61 DM: 6
;
;----------------------------------------------------------------------------------------------
INT2416
INT24
RLF AARGB0, W ; save sign in SIGN.7
RRF SIGN, F
BSF AARGB0,MSB ; make MSB explicit
MOVF EXP,W ; test for zero argument
BTFSS _Z
GOTO INT24NOTZERO
INT24CLEAR CLRF AARGB0 ; if zero, clear AARGB0:1
CLRF AARGB1 ;
RETLW 0x00 ; and return
INT24NOTZERO
;check if exponent too high (exp >= 15), i.e. overflow
;Special case when exp == -1 and RND==1 (%1.xxx * 2^-1 = %0.1xxx)
;exp<=-2 AARGB0:1=0
;exp=-1 AARGB0:1=RND
;exp=0 AARGB0:1>>15
;exp=1 AARGB0:1>>14
;...
;exp=14 AARGB0:1>>1
;exp>=15 overflow (note that +-32768 is treated as overflow even when
;-32768 can fit in 16 bit twos complement form. But -32768 will result
;in correct answer for SAT=1 or 0, although with a set IOV flag)
ADDLW -EXPBIAS-D'15' ; check if overflow
BTFSC _C
GOTO SETIOV16
XORLW 0xFF ; get number of shifts
MOVWF EXP ; w=-1-(exp-127-15)=14-(exp-127)
ANDLW 0xF0 ; clear Z if w > 15
BTFSS _Z
GOTO INT24CLEAR ; jump to clear AARG
;do shifts
BCF _C ; first shift
RRF AARGB0, F
RRF AARGB1, F
; rounding
BTFSS EXP, 3 ; shift by 8 bits if exp >= 8
GOTO INT24SHIFTS
RLF AARGB1, w ; copy bit for rounding
MOVF AARGB0, w ; shift AARGB0:1 by 8 bits
MOVWF AARGB1
CLRF AARGB0
INT24SHIFTS BCF EXP, 3 ; limit EXP to 0..7 range
INCF EXP, F ; preincrement EXP
GOTO INT24SHIFTTEST ; jump to decrement and zero check
INT24SHIFTSL BCF _C ; shift AARGB0:1 right once
RRF AARGB0, F ; and
RRF AARGB1, F ; copy bit for rounding
INT24SHIFTTEST DECFSZ EXP, F ; repeat if necessary
GOTO INT24SHIFTSL
SHIFT2416OK BTFSC FPFLAGS,RND
BTFSS _C ; round if next bit is set
GOTO INT2416OK
INCF AARGB1,F
BTFSC _Z
INCF AARGB0,F
BTFSC AARGB0,MSB ; test for overflow
GOTO SETIOV16
INT2416OK BTFSS SIGN,MSB ; if sign bit set, negate
RETLW 0
COMF AARGB1,F
COMF AARGB0,F
INCF AARGB1,F
BTFSC _Z
INCF AARGB0,F
RETLW 0
SETIOV16 BSF FPFLAGS,IOV ; set integer overflow flag
BTFSS FPFLAGS,SAT ; test for saturation
RETLW 0xFF ; return error code in WREG
MOVLW 0x80 ; saturate to largest two's
MOVWF AARGB0 ; complement 16 bit integer
CLRF AARGB1 ; SIGN = 0, 0x 7F FF
BTFSS SIGN,MSB ; SIGN = 1, 0x 80 00
COMF AARGB0, F
BTFSS SIGN,MSB
COMF AARGB1, F
RETLW 0xFF ; return error code in WREG
;**********************************************************************************************
| file: /Techref/microchip/math/round/fp-24bint-ng.htm, 8KB, , updated: 2011/1/26 13:15, local time: 2025/10/25 09:41,
216.73.216.180,10-8-63-169:LOG IN
|
| ©2025 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://www.massmind.org/Techref/microchip/math/round/fp-24bint-ng.htm"> PIC Microcontoller Math Method </A> |
| Did you find what you needed? |
Welcome to massmind.org! |
|
Ashley Roll has put together a really nice little unit here. Leave off the MAX232 and keep these handy for the few times you need true RS232! |
.