CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Integer Fast Math Library Using 8x8 Hardware Multiplier

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
OzanGazi



Joined: 03 Mar 2008
Posts: 6

View user's profile Send private message MSN Messenger

Integer Fast Math Library Using 8x8 Hardware Multiplier
PostPosted: Fri Jan 02, 2009 6:37 am     Reply with quote

Hi all!!

in the past i was composed a fast math library for realtime RMS measurement. Now i recomposed the Library for CCS forum users.

These are functions and calculation times on 40Mhz clock...

res16=fast_SquareRoot(val32); calculation time ~105uS
res32=fast_Square(val16); calculation time ~6 uS
res32=fast_Divide32by16(val32,val16); calculation time ~60uS
res32=fast_Multiply16by16(val16,val16); calculation time ~6 uS

Code edited.. on Fri Jan 02, 2009 7:00 am
Code:

///////////////////////////////////////////////////////////////////////
//                                                                   //
//                             fastmath.c                            //
//                                                                   //
//                                                                   //
//   Integer Fast Operations Library Using 8x8 Hardware Multiplier   //
//                                                                   //
//                This Code composed by OzaNGazi                     //
//                                                                   //
//     0x010-0x01B RAM area is allocated for using asm functions     //
//                                                                   //
//     !!   Hardware Mutliplier Registers must be defined   !!       //
//                                                                   //
//          (e.g. pic18f452)                                         //
//          #byte PRODL=0xFF3                                        //
//          #byte PRODH=0xFF4                                        //
//                                                                   //
//                                                                   //
//                           Functions                               //
//                                                                   //
//    res16=fast_SquareRoot(val32);      //calculation time ~105 uS  //             
//    res32=fast_Square(val16);          //calculation time ~6 uS    // 
//    res32=fast_Divide32by16(val32);    //calculation time ~60uS    //
//    res32=fast_Multiply16by16(val16); //calculation time ~6 uS    //
//                                                                   //
//                                                                   //
///////////////////////////////////////////////////////////////////////

unsigned long fast_SquareRoot(unsigned long long kok_girdi_);
unsigned long long fast_Square(unsigned long kare_girdi_);   
unsigned long long int fast_Divide32by16(unsigned long long int Dividend_ , unsigned long int Divisor_ );
Unsigned Long long int fast_Multiply16by16(unsigned long int mul1 , unsigned long int mul2) ;   

unsigned long long fast_Square(unsigned long kare_girdi_)
   {
 
   unsigned long long Kare_Sonuc;
   #locate Kare_Sonuc = 0x010
   #Byte SQRES0 = 0x010
   #Byte SQRES1 = 0x011
   #Byte SQRES2 = 0x012
   #Byte SQRES3 = 0x013
   
   unsigned long Kare_Girdi;
   #locate Kare_Girdi = 0x014
   #Byte ARG1L = 0x014
   #Byte ARG1H = 0x015
     
   kare_girdi=kare_girdi_;
   
   #asm
   ; *******************************************************************
   ; *********** 16 X 16 Unsigned Square *****************************
   ; SQRES3:SQRES0 = ARG1H:ARG1L ^2
Sq16:
   movf ARG1L, W
   mulwf ARG1L ; ARG1L * ARG2L ->
   ; PRODH:PRODL
   movff PRODH, SQRES1 ;
   movff PRODL, SQRES0 ;
   movf ARG1H, W
   mulwf ARG1H ; ARG1H * ARG2H ->
   ; PRODH:PRODL
   movff PRODH, SQRES3 ;
   movff PRODL, SQRES2 ;
   movf ARG1L, W
   mulwf ARG1H ; ARG1L * ARG2H ->
   ; PRODH:PRODL
   movf PRODL, W ;
   addwf SQRES1, F ; Add cross
   movf PRODH, W ; products
   addwfc SQRES2, F ;
   clrf WREG ;
   addwfc SQRES3, F ;
   movf ARG1H, W ;
   mulwf ARG1L ; ARG1H * ARG2L ->
   ; PRODH:PRODL
   movf PRODL, W ;
   addwf SQRES1, F ; Add cross
   movf PRODH, W ; products
   addwfc SQRES2, F ;
   clrf WREG ;
   addwfc SQRES3, F ;
   
   #endasm
   
   return(Kare_Sonuc);
   }
 
 
unsigned long fast_SquareRoot(unsigned long long kok_girdi_)
     {
     
     unsigned long long Kare_Sonuc;
     unsigned long Kare_Girdi;

     unsigned long long Kok_Girdi;
     unsigned long Kok_Sonuc;

     
     #locate Kare_Sonuc = 0x010
     #Byte SQRES0 = 0x010
     #Byte SQRES1 = 0x011
     #Byte SQRES2 = 0x012
     #Byte SQRES3 = 0x013

     #locate Kare_Girdi = 0x014
     #Byte ARG1L = 0x014
     #Byte ARG1H = 0x015

     #locate Kok_Girdi = 0x016
     #Byte ARGA0 = 0x016
     #Byte ARGA1 = 0x017
     #Byte ARGA2 = 0x018
     #Byte ARGA3 = 0x019


     #locate Kok_Sonuc = 0x01A
     #Byte RES0 = 0x01A
     #Byte RES1 = 0x01B
         
     unsigned int temp0,temp1,bitloc0,bitloc1;
     
     kok_girdi=kok_girdi_;
     
     #asm

square:
   
   ; *******************************************************************
   ; ******************** Square Root **********************************
   ; Sqrt32(ARGA3:ARGA2:ARGA1:ARGA0) = RES1:RES0

Sqrt32:
   clrf TEMP0 ; clear the temp solution
   clrf TEMP1
   clrf BITLOC0 ; setup the first bit
   clrf RES0
   movlw 0x80
   movwf BITLOC1 ; BitLoc = 0x8000
   movwf RES1 ; RES = 0x8000
Squar16:
   movff RES0, ARG1L ; square the guess
   movff RES1, ARG1H
   call Sq16
   movf SQRES0, W ; ARGA - PROD test
   subwf ARGA0, W
   movf SQRES1, W
   subwfb ARGA1, W
   movf SQRES2, W
   subwfb ARGA2, W
   movf SQRES3, W
   subwfb ARGA3, W
   btfsc STATUS,0
   bra NxtBt16 ; if positive then next bit
   ; if negative then rotate right
   addlw 0x00 ; clear carry
   movff TEMP0, RES0 ; move last good value back into RES0
   movff TEMP1, RES1
   rrcf BITLOC1, F ; then rotote the bit and put it
   rrcf BITLOC0, F
   movf BITLOC1, W ; back into RES1:RES0
   iorwf RES1, F
   movf BITLOC0, W
   iorwf RES0, F
   btfsc STATUS, 0 ; if last value was tested then get
   bra Done32 ; out
   bra Squar16 ; elso go back for another test
NxtBt16:
   addlw 0x00 ; clear carry
   movff RES0, TEMP0 ; copy the last good approximation
   movff RES1, TEMP1
   rrcf BITLOC1, F ; rotate the bit location register
   rrcf BITLOC0, F
   movf BITLOC1, W ; and put back into RES1:RES0
   iorwf RES1, F
   movf BITLOC0, W
   iorwf RES0, F
   btfsc STATUS, 0 ; if last value was tested then get
   bra Done32 ; out
   bra Squar16
   
Done32:
   movff TEMP0,RES0 ; put the final result in RES1:RES0
   movff TEMP1,RES1
   bra over
         
   ; *******************************************************************
   ; *********** 16 X 16 Unsigned Square *****************************
   ; SQRES3:SQRES0 = ARG1H:ARG1L ^2
Sq16:
   movf ARG1L, W
   mulwf ARG1L ; ARG1L * ARG2L ->
   ; PRODH:PRODL
   movff PRODH, SQRES1 ;
   movff PRODL, SQRES0 ;
   movf ARG1H, W
   mulwf ARG1H ; ARG1H * ARG2H ->
   ; PRODH:PRODL
   movff PRODH, SQRES3 ;
   movff PRODL, SQRES2 ;
   movf ARG1L, W
   mulwf ARG1H ; ARG1L * ARG2H ->
   ; PRODH:PRODL
   movf PRODL, W ;
   addwf SQRES1, F ; Add cross
   movf PRODH, W ; products
   addwfc SQRES2, F ;
   clrf WREG ;
   addwfc SQRES3, F ;
   movf ARG1H, W ;
   mulwf ARG1L ; ARG1H * ARG2L ->
   ; PRODH:PRODL
   movf PRODL, W ;
   addwf SQRES1, F ; Add cross
   movf PRODH, W ; products
   addwfc SQRES2, F ;
   clrf WREG ;
   addwfc SQRES3, F ;
   return
over:
   #endasm
   return(kok_sonuc);
     }
     
Unsigned Long long int Fast_Divide32by16(unsigned long long int Dividend_ , unsigned long int Divisor_ )
     
   {
   unsigned int bitcnt;
   unsigned Long long int Dividend;
   #locate dividend =0x010
   #byte divid0 =0x010
   #byte divid1 =0x011
   #byte divid2 =0x012
   #byte divid3 =0x013
     
   unsigned long int Divisor;     
   #locate Divisor =0x014
   #byte DivisL =0x014
   #byte DivisH =0x015
     
   unsigned long int Remdr;
   #locate Remdr =0x016
   #byte RemdrL =0x016
   #byte RemdrH =0x017
     
   Dividend=Dividend_;
   Divisor=Divisor_;
         
     #asm
     
divide:
   movlw 0x20      ; 32-bit divide by 16-bit
   movwf bitcnt
   clrf remdrH   ; Clear remainder
   clrf remdrL

dvloop:
       bcf STATUS,0          ; Set quotient bit to 0
                     ; Shift left dividend and quotient
       rlcf divid0,f    ; lsb
       rlcf divid1,f
       rlcf divid2,f
       rlcf divid3,f    ; lsb into carry
       rlcf remdrL,f    ; and then into partial remainder
       rlcf remdrH,f

       btfsc STATUS,0         ; Check for overflow
       goto subd
       movf divisH,W  ; Compare partial remainder and divisor
       subwf remdrH,w
       btfss STATUS,2
       goto testgt   ; Not equal so test if remdrH is greater
       movf divisL,W  ; High bytes are equal, compare low bytes
       subwf remdrL,w
testgt:
       btfss STATUS,0          ; Carry set if remdr >= divis
       goto remrlt

subd:   
       movf divisL,W  ; Subtract divisor from partial remainder
       subwf remdrL
       btfss STATUS,0           ; Test for borrow

       decf remdrH   ; Subtract borrow
       movf divisH,w
       subwf remdrH
       bsf divid0,0  ; Set quotient bit to 1
                     ; Quotient replaces dividend which is lost
remrlt:
       decfsz bitcnt
       goto dvloop
           
     #endasm
     
     return(dividend);
     
     }
     
Unsigned Long long int Fast_Multiply16by16(unsigned long int mul1_ , unsigned long int mul2_)     
   {

   unsigned long int wrd;
   unsigned long int luk;
   unsigned long long int res;
   unsigned int C3;

   #locate res = 0x010
   #locate wrd = 0x010
   #Byte wrd_L = 0x010
   #Byte wrd_H = 0x011

   #locate ext = 0x012
   #Byte ext_L = 0x012
   #Byte ext_H = 0x013
   
   #locate luk = 0x014
   #Byte luk_L = 0x014
   #Byte luk_H = 0x015

   wrd=mul1_;
   luk=mul2_;

   #asm
   
;Multiplication 16bit * 16bit -> 32bit
;WRD * LUK -> EXTWRD

;detailed: WRD_H:WRD_L * LUK_H:LUK_L -> EXT_H:EXT_L:WRD_H:WRD_L
;LUK value remains. Affected registers: temp reg C3

MULW:  movf    WRD_H,w
       mulwf   LUK_H    ; LUK_H * WRD_H
       movff   PRODH,EXT_H
       movff   PRODL,EXT_L
       movf    WRD_L,w
       mulwf   LUK_L    ; LUK_L * WRD_L
       movff   PRODH,C3
       movff   PRODL,WRD_L
       mulwf   LUK_H    ; LUK_H * WRD_L
       movf    PRODL,w
       addwf   C3,f    ; Add cross
       movf    PRODH,w    ; products
       addwfc  EXT_L,f
       clrf    WREG
       addwfc  EXT_H,f
       movf    WRD_H,w
       mulwf   LUK_L    ; LUK_L * WRD_H
       movf    PRODL,w    ;
       addwf   C3,w    ; Add cross
       movwf   WRD_H
       movf    PRODH,w    ; products
       addwfc  EXT_L,f
       clrf    WREG
       addwfc  EXT_H,f
#endasm
             
   return(res);
       
}
   
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group