// Test fixed arithmetic macros #include #include #include //for square root only #include //I like these definitions #define begin { #define end } //===The fixed macros========================================= #define int2fix(a) (((int)(a))<<8) //Convert char to fix #define fix2intSlow(a) ((signed char)((a)>>8)) //Convert fix to char #define float2fix(a) ((int)((a)*256.0)) //Convert float to fix #define fix2float(a) ((float)(a)/256.0) //Convert fix to float #define multfixSlow(a,b) ((int)((((long)(a))*((long)(b)))>>8)) //multiply two fixed # //see below for the fast version #define divfix(a,b) ((int)((((long)(a))<<8)/((long)(b)))) //divide two fixed # //lsqrt is in math.h #define sqrtfixSlow(a) (lsqrt(((long)(a))<<8)) //square root //==Fast fixed multiply================================= char fix2int(int a) begin #asm ldd r30, Y+1 ;moves the high byte of the input to low byte #endasm end //==Fast fixed multiply================================= int multfix(int a,int b) begin #asm ;****************************************************************************** ;* ;* FUNCTION ;* muls16x16_24 ;* DECRIPTION ;* Signed multiply of two 16bits numbers with 24bits result. ;* USAGE ;* r31:r30:rxx = r23:r22 * r21:r20 ;****************************************************************************** push r20 push r21 LDD R22,Y+2 ;load a LDD R23,Y+3 LD R20,Y ;load b LDD R21,Y+1 muls r23, r21 ; (signed)ah * (signed)bh mov r31, r0 ;r18, r0 mul r22, r20 ; al * bl mov r30, r1 ;movw r17:r16, r1:r0 ;mov r16, r0 mulsu r23, r20 ; (signed)ah * bl add r30, r0 ;r17, r0 adc r31, r1 ;r18, r1 mulsu r21, r22 ; (signed)bh * al add r30, r0 ;r17, r0 adc r31, r1 ;r18, r1 pop r21 pop r20 #endasm end //======================================================== int sqrtfix(int a) begin int hi, lo, guess, slp, in, d; //assign linear least squares values if (a>=0x7900) {slp=11;in=1489;d=4;} //121 to 127 else if (a>=0x6400) {slp=12;in=1369;d=9;} //100 else if (a>=0x5100) {slp=13;in=1254;d=7;} //81 else if (a>=0x4000) {slp=15;in=1087;d=5;} //64 else if (a>=0x3100) {slp=17;in=959;d=5;} //49 else if (a>=0x2400) {slp=20;in=857;d=6;} //36 else if (a>=0x1900) {slp=23;in=703;d=9;} //25 else if (a>=0x1000) {slp=28;in=575;d=10;} //16 else if (a>=0x0900) {slp=36;in=447;d=9;} //9 else if (a>=0x0400) {slp=51;in=318;d=10;} //4 else if (a>=0x0200) {slp=75;in=217;d=5;} //2 else if (a>=0x0100) {slp=106;in=154;d=3;} //1 else if (a>=0x0040) {slp=168;in=94;d=8;} //1/4 to 1 else {slp=502;in=22;d=10;} // 1/4 //do the linear fit guess = multfix(a,slp)+in; lo = guess - d; hi = guess + d; //iterate to get the last few bits while ((hi-lo) > 0x0002) begin //TCNT1=0; TCCR1B=1; if (multfix(guess,guess)>=a) hi = guess; else lo = guess; guess = ((hi+lo)>>1); //TCCR1B=0; printf("%d ",TCNT1); end return guess; end //======================================================== signed char cIn; //an input integer float fIn; //an input float char fInString[16]; signed int cInFix, fInFix, prod, ratio, root, s, c; char i; //===CORDIC================================================ //for CORDIC sine/cos only flash int Angles[]={ float2fix(45.0), float2fix(26.565), float2fix(14.0362), float2fix(7.12502), float2fix(3.57633), float2fix(1.78991), float2fix(0.895174),float2fix(0.447614),float2fix(0.223811), float2fix(0.111906),float2fix(0.055953),float2fix(0.027977) }; //From: http://my.execpc.com/~geezer/embed/cordic.htm --- geezer@execpc.com int sinefix(int TargetAngle) begin int X, Y, CurrAngle; unsigned Step; Y=0; CurrAngle=0; X = 0x009b; //0.607 for(Step=0; Step < 12; Step++) { int NewX; if(TargetAngle > CurrAngle) { NewX=X - (Y >> Step); Y=(X >> Step) + Y; X=NewX; CurrAngle += Angles[Step]; } else { NewX=X + (Y >> Step); Y=-(X >> Step) + Y; X=NewX; CurrAngle -= Angles[Step]; }} return Y; end //From: http://my.execpc.com/~geezer/embed/cordic.htm --- geezer@execpc.com int cosfix(int TargetAngle) begin int X, Y, CurrAngle; unsigned Step; Y=0; CurrAngle=0; X = 0x009b; //0.607; for(Step=0; Step < 12; Step++) { int NewX; if(TargetAngle > CurrAngle) { NewX=X - (Y >> Step); Y=(X >> Step) + Y; X=NewX; CurrAngle += Angles[Step]; } else { NewX=X + (Y >> Step); Y=-(X >> Step) + Y; X=NewX; CurrAngle -= Angles[Step]; }} return X; end //========================================================== void main(void) begin //serial setop for debugging using printf, etc. UCSRB = 0x18 ; UBRRL = 103 ; putsf("\r\nStarting...\r\n"); while(1) begin //test int2fix printf("\r\nenter a signed char:") ; scanf("%d",&cIn);printf("%d",cIn); cInFix = int2fix(cIn); printf(" fixed rep:%04x\r\n",cInFix); //test float2fix printf("enter a float:") ; scanf("%s",fInString); fIn = atof(fInString); printf("%f",fIn); fInFix = float2fix(fIn); printf(" fixed rep:%04x\r\n",fInFix); //test multiply and fix2float and fix2int prod = multfix(fInFix, cInFix) ; printf("%d*%f=%f", cIn, fIn, fix2float(prod)) ; printf(" fixed rep:%04x\r\n", prod) ; //test divide and fix2float prod = divfix(cInFix, fInFix) ; printf("%d/%f=%f\r\n", cIn, fIn, fix2float(prod)) ; //test sqrtfix root = sqrtfix(fInFix); printf("sqrt(%f)=%f\r\n", fIn,fix2float(root)) ; s = sinefix(fInFix); printf("sin(%f)=%f\r\n", fIn,fix2float(s)) ; c = cosfix(fInFix); printf("cos(%f)=%f\r\n", fIn,fix2float(c)) ; //============================================ TCCR1B = 1 ; TCNT1 = 0; prod = multfix(fInFix, cInFix) ; TCCR1B = 0; printf("multfix cycles=%d\n\r",TCNT1) ; TCCR1B = 1 ; TCNT1 = 0; prod = multfixSlow(fInFix, cInFix) ; TCCR1B = 0; printf("multfixSlow cycles=%d\n\r",TCNT1) ; TCCR1B = 1 ; TCNT1 = 0; fIn = fIn * fIn ; TCCR1B = 0; printf("multfloat cycles=%d\n\r",TCNT1) ; //============================================ TCCR1B = 1 ; TCNT1 = 0; prod = divfix(fInFix, cInFix) ; TCCR1B = 0; printf("divfix cycles=%d\n\r",TCNT1) ; TCCR1B = 1 ; TCNT1 = 0; fIn = fIn / fIn ; TCCR1B = 0; printf("divfloat cycles=%d\n\r",TCNT1) ; //============================================ TCCR1B = 1 ; TCNT1 = 0; prod = sqrtfix(fInFix) ; TCCR1B = 0; printf("sqrtfix cycles=%d\n\r",TCNT1) ; TCCR1B = 1 ; TCNT1 = 0; prod = sqrtfixSlow(fInFix) ; TCCR1B = 0; printf("sqrtfixSlow cycles=%d\n\r",TCNT1) ; TCCR1B = 1 ; TCNT1 = 0; fIn = sqrt(fIn) ; TCCR1B = 0; printf("sqrtfloat cycles=%d\n\r",TCNT1) ; //============================================ TCCR1B = 1 ; TCNT1 = 0; i = fix2int(fInFix) ; TCCR1B = 0; printf("fix2int cycles=%d\n\r",TCNT1) ; TCCR1B = 1 ; TCNT1 = 0; i = fix2intSlow(fInFix) ; TCCR1B = 0; printf("fix2intSlow cycles=%d\n\r",TCNT1) ; end end