please dont rip this site

PIC Microcontoller Math Method

Fixed AN575 INT24 routine (round floating point to 24 bit integer)

by Nikolai Golovchenko

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: 2024/10/4 02:01,
TOP NEW HELP FIND: 
3.238.82.77:LOG IN
©2024 PLEASE DON'T RIP! THIS SITE CLOSES OCT 28, 2024 SO LONG AND THANKS FOR ALL THE FISH!

 ©2024 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?
Please DO link to this page! Digg it! / MAKE!

<A HREF="http://piclist.com/techref/microchip/math/round/fp-24bint-ng.htm"> PIC Microcontoller Math Method </A>

After you find an appropriate page, you are invited to your to this massmind site! (posts will be visible only to you before review) Just type a nice message (short messages are blocked as spam) in the box and press the Post button. (HTML welcomed, but not the <A tag: Instead, use the link box to link to another page. A tutorial is available Members can login to post directly, become page editors, and be credited for their posts.


Link? Put it here: 
if you want a response, please enter your email address: 
Attn spammers: All posts are reviewed before being made visible to anyone other than the poster.
Did you find what you needed?

  PICList 2024 contributors:
o List host: MIT, Site host massmind.org, Top posters @none found
- Page Editors: James Newton, David Cary, and YOU!
* Roman Black of Black Robotics donates from sales of Linistep stepper controller kits.
* Ashley Roll of Digital Nemesis donates from sales of RCL-1 RS232 to TTL converters.
* Monthly Subscribers: Gregg Rew. on-going support is MOST appreciated!
* Contributors: Richard Seriani, Sr.
 

Welcome to piclist.com!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  .