piclist 2001\04\06\103828a >
Thread: Rounding to closest 1's multiple, code enclosed :)
www.piclist.com/techref/microchip/devices.htm?key=pic
flavicon
face BY : Kübek Tonyemail (remove spam text)



Hi,
as I promised I've hammered out some rounding code and
will attach the rounding to closest 1s multiple below.
The rounding to closest 10's multiple is posted separately.

Some minor comments:
It's coded for 24 bit input/output trough fsr0,
uses some 18Cxx specific instructions ( wouldn't be
to hard to convert to other pic's ).
It's not fully omptimized, I'll leave that as an exerzice
to the user ( there are some places that can be improved )
The rounding takes about 88 instructions worst case.
As far as I can tell there really are no faster options
to round an 24 bit value. But please prove me wrong :)

And without the input from Bob,Roman and Scott it sure would
have been a rougher ride. Thanks.

Use at will.


; ***********************************************************************
; ROUND_ONES_FSR0_24bit - Rounds 24 bit unsigned value value pointed to by
fsr0
; according to (ones)granularity in w
; FSR0 must point to MSB of input, output will overwrite input at exit
; Granularity can be 0x05, 0x02 ( others not tested )
; 0x05 round to nearest decimal '5', 0x02 round to nearest decimal '2' etc.
; In other words low nibble of w decides the granularity for the ones digit
; Other granularities are untested and may/may not nork.
;
; Executes in about 88 cycles worst case
; About 65 instructions are used. I.e mostly unrolled code
;
; Algorithm:
; * Adds half granularity to input. ( i.e. for granularity 0x05 ( 5 ) 2 is
added )
; * 'Exctract' each bit's addition to the ones digit
;    After the actual 'extraction' it is normalized ( to 0-9 range ).
; * If ones digit is larger then granularity, granulairty is subtracted from
it
;   until next subtraction generates negative result.
; * Subtract the result from the input and overwrite with output.
;
;                      
; Ram usage ( all in access bank ):
; ARG2_24+1     1 byte 'ones'
; Temp          1 byte 'granularity' ( i.e. input in w )
;

ROUND_ONES_FSR0_24bit
       GLOBAL  ROUND_ONES_FSR0_24bit
       ; save granularity
       MOVWF   Temp,A
       ; set pointer to lsb of input
       MOVF    POSTINC0,W,A
       MOVF    PREINC0,W,A     ; pointer now to lsb and lsb in w
       ; add half of granularity(real) to input
       BCF     STATUS,C
       RRCF    Temp,W,A
       ADDWF   POSTDEC0,F,A    ; add to lsb and set pointer to middle byte
       MOVF    INDF0,W,A       ; get middle byte
       BTFSC   STATUS,C
       ADDLW   D'1'            ; propagate the carry
       MOVWF   POSTDEC0,A      ; save it and set pointer to msb
       BTFSC   STATUS,C
       INCF    INDF0,F,A       ; propagate the carry and leave pointer to
msb

       ; * calcualte top byte byte low nibble
       MOVF    INDF0,W,A       ;
       ANDLW   b'00001111'     ; mask out lowest nibble
       BTFSC   INDF0,0,A       ; lowest bit set in low nibble ?
       ADDLW   D'5'            ; yes add  5, it's worth '6' not 1
       MOVWF   ARG2_24+1,A     ; start value for the ones
       ; calcualte top byte high nibble
       SWAPF   INDF0,W,A       ;
       ANDLW   b'00001111'     ; mask out lowest nibble
       BTFSC   POSTINC0,4,A    ; lowest bit set in high nibble ? *set
pointer to middle byte *
       ADDLW   D'5'            ; yes add  5, it's worth '6' not 1
       ADDWF   ARG2_24+1,F,A   ; add it to ones
       ; * calcualte middle byte low nibble
       MOVF    INDF0,W,A       ;
       ANDLW   b'00001111'     ; mask out lowest nibble
       BTFSC   INDF0,0,A       ; lowest bit set in low nibble ?
       ADDLW   D'5'            ; yes add  5, it's worth '6' not 1
       ADDWF   ARG2_24+1,F,A   ; add it to ones
       ; calcualte middle byte high nibble
       SWAPF   INDF0,W,A       ;
       ANDLW   b'00001111'     ; mask out lowest nibble
       BTFSC   POSTINC0,4,A    ; lowest bit set in high nibble ?*set
pointer to lowest byte *
       ADDLW   D'5'            ; yes add  5, it's worth '6' not 1
       ADDWF   ARG2_24+1,F,A   ; add it to ones
       ; * calculate lowest nibble of lowest byte
       MOVF    INDF0,W,A       ;
       ANDLW   b'00001111'     ; mask out lowest nibble
       ADDWF   ARG2_24+1,F,A   ; add it to ones
       ; calculate top nibble 'ones' byte
       SWAPF   INDF0,W,A       ;
       ANDLW   b'00001111'     ; mask out lowest (prev. highest) nibble
       BTFSC   INDF0,4,A       ; lowest bit set in top nibble ?
       ADDLW   D'5'            ; yes add  5, it's worth '6' not 1
       ADDWF   ARG2_24+1,F,A   ; add it to ones

       ; pointer fsr0 points to lsb of input here
ROUND_ONES_FSR0_NORM
       ; *** ones updated now we need to normalize it ( i.e. remove
everything above 10 )
       ; Maximum value for the ones: 109
       ; we start by subtracting 30 from the ones until negative, then add
ten until positive again
       ; after which we know it's in 0-9 range
       ; subtract 30 from ones        
       MOVLW   D'30'
ROUND_ONES_FSR0_SUB30
       ; subtract 30 from ones
       SUBWF   ARG2_24+1,F,A
       SKPNC   ; overflow, i.e. negative then add 10 until positive again
       GOTO    ROUND_ONES_FSR0_SUB30
       ; add 10 until positive again
       MOVLW   D'10'
ROUND_ONES_FSR0_ADD10
       ; add 10 to ones
       ADDWF   ARG2_24+1,F,A  
       SKPC    ; positive ?
       GOTO    ROUND_ONES_FSR0_ADD10   ; nope still negative
       ; now ones are positive and below 10, i.e. we have successfully
subtracted
       ; the ones digit for the 24 bit input
       
       ; ** calculate granularity diff in the ones digit
       ; subtract granularity from the ones byte
       MOVF    ARG2_24+1,W,A   ; start value
ROUND_ONES_FSR0_GRAN_CHK
       MOVWF   ARG2_24+1,A     ; save start value ( or concecutive values )
       MOVF    Temp,W,A        ; get granularity
       ; subtract it from the tens
       SUBWF   ARG2_24+1,W,A
       ; check if negative or positive
       ; if positive/zero save result and try again
       BTFSS   STATUS,N
       GOTO    ROUND_ONES_FSR0_GRAN_CHK
       ; get the diff into w
       MOVF    ARG2_24+1,W,A   ; granularity diff
       ; now we subtract this from the input
       SUBWF   POSTDEC0,F,A    ; subtract and set pointer to middle byte
       SKPC    
       DECF    INDF0,F,A       ; propagate the borrow
       MOVF    POSTDEC0,W      ; set pointer to msb
       SKPC    
       DECF    INDF0,F,A       ; propagate the borrow and leave pointer to
msb of input
                               
       RETURN





Tony Kübek, Flintab AB            
²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²
E-mail: KILLspamtony.kubekRemoveMEspamflintab.com
²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²

--
http://www.piclist.com hint: To leave the PICList
EraseMEpiclist-unsubscribe-requestspam_OUTspamspammitvma.mit.edu


<200104061432.QAA25481@mn10.swip.net> quoted-printable

See also: www.piclist.com/techref/microchip/devices.htm?key=pic
Reply You must be a member of the piclist mailing list (not only a www.piclist.com member) to post to the piclist. This form requires JavaScript and a browser/email client that can handle form mailto: posts.
Subject (change) Rounding to closest 1's multiple, code enclosed :)

month overview.

new search...