Full Version : Golovchenko's Float to 24-Bit Conversion (PIC ASM)
avr >>PIC 8051 ZILOG ARM TI H8 ETC >>Golovchenko's Float to 24-Bit Conversion (PIC ASM)


Admin3- 04-18-2006
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)

3) there is something wrong with the rounding

»
[/code]
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).
CODE

#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



Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.