; CC7A Ver 1.0D, Copyright (c) B Knudsen Data ; C compiler for the PIC18 microcontrollers ; ************ 24. Feb 2011 12:28 ************* processor 17C766 radix DEC WREG EQU 0x0A Carry EQU 0 PA0 EQU 5 arg1_3 EQU 0x20 arg2_3 EQU 0x23 rm EQU 0x26 counter EQU 0x29 c2 EQU 0x2A sign_2 EQU 0x2B ad_data EQU 0x2C tx EQU 0x120 av EQU 0x123 a EQU 0x129 vx EQU 0x12C prev EQU 0x220 kp EQU 0x223 GOTO main ; FILE 17\demo-fxm.c ; ;#pragma chip PIC17C766 // select device ; ;// FIRST ADD THE INTERRUPT ROUTINE (if any) ;// #include "app-int.c" ; ;#pragma rambank 0 ;#pragma codepage 1 ORG 0x2000 ; FILE 18\math24x.h ;#pragma library 1 ;/* ;fixed16_8 operator* _xmul16_8( fixed16_8 arg1, fixed16_8 arg2); ;fixedU16_8 operator* _xmulU16_8( fixedU16_8 arg1, fixedU16_8 arg2); ;fixed16_8 operator/ _xdiv16_8( fixed16_8 arg1, fixed16_8 arg2); ;fixedU16_8 operator/ _xdivU16_8( fixedU16_8 arg1, fixedU16_8 arg2); ;fixed8_16 operator* _xmul8_16( fixed8_16 arg1, fixed8_16 arg2); ;fixedU8_16 operator* _xmulU8_16( fixedU8_16 arg1, fixedU8_16 arg2); ;fixed8_16 operator/ _xdiv8_16( fixed8_16 arg1, fixed8_16 arg2); ;fixedU8_16 operator/ _xdivU8_16( fixedU8_16 arg1, fixedU8_16 arg2); ;*/ ; ;// DEFINABLE SYMBOLS (in the application code): ;//#define FX_OPTIM_SPEED // optimize for SPEED: default ;//#define FX_OPTIM_SIZE // optimize for SIZE ; ;#if __CoreSet__ < 1200 || __CoreSet__ >= 2100 ; #error math24x.h does not support the selected device ;#endif ; ;#if __CoreSet__ < 1600 ; #define genAdd(r,a) W=a; btsc(Carry); W=incsz(a); r+=W ; #define genSub(r,a) W=a; btss(Carry); W=incsz(a); r-=W ; #define genAddW(r,a) W=a; btsc(Carry); W=incsz(a); W=r+W ; #define genSubW(r,a) W=a; btss(Carry); W=incsz(a); W=r-W ;#else ; #define genAdd(r,a) W=a; r=addWFC(r) ; #define genSub(r,a) W=a; r=subWFB(r) ; #define genAddW(r,a) W=a; W=addWFC(r) ; #define genSubW(r,a) W=a; W=subWFB(r) ;#endif ; ;#if defined FX_OPTIM_SIZE ; // do not use 8*8 bit HW multiplier ;#elif __CoreSet__ == 1700 || __CoreSet__ == 1800 ; #define hw_mult8x8(a,b) W = a; multiply(b) ; #define loRES PRODL ; #define hiRES PRODH ;#elif __CoreSet__ == 2000 ; #define hw_mult8x8(a,b) W = a; multiply(b) ; #define loRES W ; #define hiRES MULH ;#endif ; ; ; ;fixed16_8 operator* _xmul16_8( fixed16_8 arg1, fixed16_8 arg2) ;{ _xmul16_8 ; fixed16_8 rval; ; char sign = arg1.high8 ^ arg2.high8; ; if (arg1 < 0) ; arg1 = -arg1; ; if (arg2 < 0) ; arg2 = -arg2; ; ; #ifdef hw_mult8x8 ; ; hw_mult8x8( arg1.low8, arg2.low8); // p1 ; rval.low8 = hiRES; ; rval.high16 = 0; ; ; hw_mult8x8( arg1.mid8, arg2.low8); // p2 ; rval.low8 += loRES; ; genAdd( rval.mid8, hiRES); ; genAdd( rval.high8, 0); ; ; hw_mult8x8( arg1.low8, arg2.mid8); // p2 ; rval.low8 += loRES; ; genAdd( rval.mid8, hiRES); ; genAdd( rval.high8, 0); ; ; hw_mult8x8( arg1.high8, arg2.low8); // p3 ; rval.mid8 += loRES; ; genAdd( rval.high8, hiRES); ; ; hw_mult8x8( arg1.mid8, arg2.mid8); // p3 ; rval.mid8 += loRES; ; genAdd( rval.high8, hiRES); ; ; hw_mult8x8( arg1.low8, arg2.high8); // p3 ; rval.mid8 += loRES; ; genAdd( rval.high8, hiRES); ; ; hw_mult8x8( arg1.high8, arg2.mid8); // p4 ; rval.high8 += loRES; ; ; hw_mult8x8( arg1.mid8, arg2.high8); // p4 ; rval.high8 += loRES; ; ; #else ; ; char counter = sizeof(arg1)*8; ; char rvalL = 0; ; do { ; Carry = 0; ; rvalL = rl( rvalL); ; rval = rl( rval); ; arg1 = rl( arg1); ; if (Carry) { ; rvalL += arg2.low8; ; genAdd( rval.low8, arg2.mid8); ; genAdd( rval.mid8, arg2.high8); ; if (Carry) ; rval.high8++; ; } ; counter = decsz(counter); ; } while (1); ; ; #endif ; ; if (sign & 0x80) ; rval = -rval; ; return rval; ;} ; ; ;fixedU16_8 operator* _xmulU16_8( fixedU16_8 arg1, fixedU16_8 arg2) ;{ _xmulU16_8 ; fixedU16_8 rval; ; ; #ifdef hw_mult8x8 ; ; hw_mult8x8( arg1.low8, arg2.low8); // p1 ; rval.low8 = hiRES; ; rval.high16 = 0; ; ; hw_mult8x8( arg1.mid8, arg2.low8); // p2 ; rval.low8 += loRES; ; genAdd( rval.mid8, hiRES); ; genAdd( rval.high8, 0); ; ; hw_mult8x8( arg1.low8, arg2.mid8); // p2 ; rval.low8 += loRES; ; genAdd( rval.mid8, hiRES); ; genAdd( rval.high8, 0); ; ; hw_mult8x8( arg1.high8, arg2.low8); // p3 ; rval.mid8 += loRES; ; genAdd( rval.high8, hiRES); ; ; hw_mult8x8( arg1.mid8, arg2.mid8); // p3 ; rval.mid8 += loRES; ; genAdd( rval.high8, hiRES); ; ; hw_mult8x8( arg1.low8, arg2.high8); // p3 ; rval.mid8 += loRES; ; genAdd( rval.high8, hiRES); ; ; hw_mult8x8( arg1.high8, arg2.mid8); // p4 ; rval.high8 += loRES; ; ; hw_mult8x8( arg1.mid8, arg2.high8); // p4 ; rval.high8 += loRES; ; ; #else ; ; char counter = sizeof(arg1)*8; ; char rvalL = 0; ; do { ; Carry = 0; ; rvalL = rl( rvalL); ; rval = rl( rval); ; arg1 = rl( arg1); ; if (Carry) { ; rvalL += arg2.low8; ; genAdd( rval.low8, arg2.mid8); ; genAdd( rval.mid8, arg2.high8); ; if (Carry) ; rval.high8++; ; } ; counter = decsz(counter); ; } while (1); ; ; #endif ; ; return rval; ;} ; ; ;fixed16_8 operator/ _xdiv16_8( fixed16_8 arg1, fixed16_8 arg2) ;{ _xdiv16_8 ; fixedU16_8 rm = 0; CLRF rm,1 CLRF rm+1,1 CLRF rm+2,1 ; char counter = sizeof(arg1)*8+8+1; MOVLW 33 MOVWF counter ; char c2 = sizeof(arg1)*8 + 1; MOVLW 25 MOVWF c2 ; char sign = arg1.high8 ^ arg2.high8; MOVFP arg2_3+2,WREG XORWF arg1_3+2,W MOVWF sign_2 ; if (arg1 < 0) { BTFSS arg1_3+2,7 GOTO m002 ; INVERT_ML: ; arg1 = -arg1; m001 COMF arg1_3+2,1 COMF arg1_3+1,1 COMF arg1_3,1 INCF arg1_3,1 MOVLW 0 ADDWFC arg1_3+1,1 ADDWFC arg1_3+2,1 ; if (c2 & 0x80) BTFSC c2,7 ; goto EXIT; GOTO m005 ; } ; if (arg2 < 0) m002 BTFSS arg2_3+2,7 GOTO m004 ; arg2 = -arg2; COMF arg2_3+2,1 COMF arg2_3+1,1 COMF arg2_3,1 INCF arg2_3,1 MOVLW 0 ADDWFC arg2_3+1,1 ADDWFC arg2_3+2,1 ; goto ENTRY_ML; GOTO m004 ; do { ; c2 = decsz(c2); m003 DECFSZ c2,1 ; btsc(c2.7); BTFSC c2,7 ; Carry = 0; BCF 0x04,Carry ; rm = rl( rm); RLCF rm,1 RLCF rm+1,1 RLCF rm+2,1 ; W = rm.low8 - arg2.low8; MOVFP arg2_3,WREG SUBWF rm,W ; genSubW( rm.mid8, arg2.mid8); MOVFP arg2_3+1,WREG SUBWFB rm+1,W ; genSubW( rm.high8, arg2.high8); MOVFP arg2_3+2,WREG SUBWFB rm+2,W ; if (!Carry) BTFSS 0x04,Carry ; goto ENTRY_ML; GOTO m004 ; rm.high8 = W; MOVWF rm+2 ; rm.low8 -= arg2.low8; MOVFP arg2_3,WREG SUBWF rm,1 ; genSub( rm.mid8, arg2.mid8); MOVFP arg2_3+1,WREG SUBWFB rm+1,1 ; Carry = 1; BSF 0x04,Carry ; ENTRY_ML: ; arg1 = rl( arg1); m004 RLCF arg1_3,1 RLCF arg1_3+1,1 RLCF arg1_3+2,1 ; counter = decsz(counter); DECFSZ counter,1 ; } while (1); GOTO m003 ; if (sign & 0x80) BTFSC sign_2,7 ; goto INVERT_ML; GOTO m001 ; EXIT: ; return arg1; m005 MOVFP arg1_3,WREG RETURN ;} ; ; ; ;fixedU16_8 operator/ _xdivU16_8( fixedU16_8 arg1, fixedU16_8 arg2) ;{ _xdivU16_8 ; fixedU16_8 rm = 0; ; char counter = sizeof(arg1)*8+8+1; ; char c2 = sizeof(arg1)*8 + 1; ; goto ENTRY_ML; ; do { ; c2 = decsz(c2); ; btsc(c2.7); ; Carry = 0; ; rm = rl( rm); ; if (Carry) ; goto SUBTRACT; ; W = rm.low8 - arg2.low8; ; genSubW( rm.mid8, arg2.mid8); ; genSubW( rm.high8, arg2.high8); ; if (!Carry) ; goto ENTRY_ML; ; SUBTRACT: ; rm.low8 -= arg2.low8; ; genSub( rm.mid8, arg2.mid8); ; genSub( rm.high8, arg2.high8); ; Carry = 1; ; ENTRY_ML: ; arg1 = rl( arg1); ; counter = decsz(counter); ; } while (1); ; return arg1; ;} ; ; ; ; ;fixed8_16 operator* _xmul8_16( fixed8_16 arg1, fixed8_16 arg2) ;{ _xmul8_16 ; fixed8_16 rval; ; char sign = arg1.high8 ^ arg2.high8; ; if (arg1 < 0) ; arg1 = -arg1; ; if (arg2 < 0) ; arg2 = -arg2; ; ; #ifdef hw_mult8x8 ; ; uns8 tmpL; ; ; hw_mult8x8( arg1.low8, arg2.low8); // p1 ; tmpL = hiRES; ; rval = 0; ; ; hw_mult8x8( arg1.mid8, arg2.low8); // p2 ; tmpL += loRES; ; genAdd( rval.low8, hiRES); ; genAdd( rval.mid8, 0); ; ; hw_mult8x8( arg1.low8, arg2.mid8); // p2 ; tmpL += loRES; ; genAdd( rval.low8, hiRES); ; genAdd( rval.mid8, 0); ; ; hw_mult8x8( arg1.high8, arg2.low8); // p3 ; rval.low8 += loRES; ; genAdd( rval.mid8, hiRES); ; genAdd( rval.high8, 0); ; ; hw_mult8x8( arg1.mid8, arg2.mid8); // p3 ; rval.low8 += loRES; ; genAdd( rval.mid8, hiRES); ; genAdd( rval.high8, 0); ; ; hw_mult8x8( arg1.low8, arg2.high8); // p3 ; rval.low8 += loRES; ; genAdd( rval.mid8, hiRES); ; genAdd( rval.high8, 0); ; ; hw_mult8x8( arg1.high8, arg2.mid8); // p4 ; rval.mid8 += loRES; ; genAdd( rval.high8, hiRES); ; ; hw_mult8x8( arg1.mid8, arg2.high8); // p4 ; rval.mid8 += loRES; ; genAdd( rval.high8, hiRES); ; ; hw_mult8x8( arg1.high8, arg2.high8); // p5 ; rval.high8 += loRES; ; ; #else ; ; char counter = sizeof(arg2)*8; ; uns8 rvalH = 0; ; rval.high16 = 0; ; ; do { ; arg2 = rr( arg2); ; if (Carry) { ; rval.mid8 += arg1.low8; ; genAdd( rval.high8, arg1.mid8); ; genAdd( rvalH, arg1.high8); ; } ; rvalH = rr( rvalH); ; rval = rr( rval); ; counter = decsz(counter); ; } while (1); ; ; #endif ; ; if (sign & 0x80) ; rval = -rval; ; return rval; ;} ; ; ;fixedU8_16 operator* _xmulU8_16( fixedU8_16 arg1, fixedU8_16 arg2) ;{ _xmulU8_16 ; fixedU8_16 rval; ; ; #ifdef hw_mult8x8 ; ; uns8 tmpL; ; ; hw_mult8x8( arg1.low8, arg2.low8); // p1 ; tmpL = hiRES; ; rval = 0; ; ; hw_mult8x8( arg1.mid8, arg2.low8); // p2 ; tmpL += loRES; ; genAdd( rval.low8, hiRES); ; genAdd( rval.mid8, 0); ; ; hw_mult8x8( arg1.low8, arg2.mid8); // p2 ; tmpL += loRES; ; genAdd( rval.low8, hiRES); ; genAdd( rval.mid8, 0); ; ; hw_mult8x8( arg1.high8, arg2.low8); // p3 ; rval.low8 += loRES; ; genAdd( rval.mid8, hiRES); ; genAdd( rval.high8, 0); ; ; hw_mult8x8( arg1.mid8, arg2.mid8); // p3 ; rval.low8 += loRES; ; genAdd( rval.mid8, hiRES); ; genAdd( rval.high8, 0); ; ; hw_mult8x8( arg1.low8, arg2.high8); // p3 ; rval.low8 += loRES; ; genAdd( rval.mid8, hiRES); ; genAdd( rval.high8, 0); ; ; hw_mult8x8( arg1.high8, arg2.mid8); // p4 ; rval.mid8 += loRES; ; genAdd( rval.high8, hiRES); ; ; hw_mult8x8( arg1.mid8, arg2.high8); // p4 ; rval.mid8 += loRES; ; genAdd( rval.high8, hiRES); ; ; hw_mult8x8( arg1.high8, arg2.high8); // p5 ; rval.high8 += loRES; ; ; #else ; ; char counter = sizeof(arg2)*8; ; uns8 rvalH = 0; ; rval.high16 = 0; ; do { ; arg2 = rr( arg2); ; if (Carry) { ; rval.mid8 += arg1.low8; ; genAdd( rval.high8, arg1.mid8); ; genAdd( rvalH, arg1.high8); ; } ; rvalH = rr( rvalH); ; rval = rr( rval); ; counter = decsz(counter); ; } while (1); ; ; #endif ; ; return rval; ;} ; ; ;fixed8_16 operator/ _xdiv8_16( fixed8_16 arg1, fixed8_16 arg2) ;{ _xdiv8_16 ; fixedU8_16 rm = 0; ; char counter = sizeof(arg1)*8+16+1; ; char c2 = sizeof(arg1)*8 + 1; ; char sign = arg1.high8 ^ arg2.high8; ; if (arg1 < 0) { ; INVERT_ML: ; arg1 = -arg1; ; if (c2 & 0x80) ; goto EXIT; ; } ; if (arg2 < 0) ; arg2 = -arg2; ; goto ENTRY_ML; ; do { ; c2 = decsz(c2); ; btsc(c2.7); ; Carry = 0; ; rm = rl( rm); ; W = rm.low8 - arg2.low8; ; genSubW( rm.mid8, arg2.mid8); ; genSubW( rm.high8, arg2.high8); ; if (!Carry) ; goto ENTRY_ML; ; rm.high8 = W; ; rm.low8 -= arg2.low8; ; genSub( rm.mid8, arg2.mid8); ; Carry = 1; ; ENTRY_ML: ; arg1 = rl( arg1); ; counter = decsz(counter); ; } while (1); ; if (sign & 0x80) ; goto INVERT_ML; ; EXIT: ; return arg1; ;} ; ; ; ;fixedU8_16 operator/ _xdivU8_16( fixedU8_16 arg1, fixedU8_16 arg2) ;{ _xdivU8_16 ; fixedU8_16 rm = 0; ; char counter = sizeof(arg1)*8+16+1; ; char c2 = sizeof(arg1)*8 + 1; ; goto ENTRY_ML; ; do { ; c2 = decsz(c2); ; btsc(c2.7); ; Carry = 0; ; rm = rl( rm); ; if (Carry) ; goto SUBTRACT; ; W = rm.low8 - arg2.low8; ; genSubW( rm.mid8, arg2.mid8); ; genSubW( rm.high8, arg2.high8); ; if (!Carry) ; goto ENTRY_ML; ; SUBTRACT: ; rm.low8 -= arg2.low8; ; genSub( rm.mid8, arg2.mid8); ; genSub( rm.high8, arg2.high8); ; Carry = 1; ; ENTRY_ML: ; arg1 = rl( arg1); ; counter = decsz(counter); ; } while (1); ; return arg1; ; FILE 17\demo-fxm.c ;#include "math24x.h" ;#pragma codepage 0 ORG 0x0001 ; ;uns16 ad_data; ;bank1 fixed16_8 tx, av, mg, a, vx; ;bank2 fixed16_8 prev, kp; ; ;void main(void) ;{ main ; vx = 3.127; MOVLW 33 MOVLR 1 MOVWF vx MOVLW 3 MOVWF vx+1 CLRF vx+2,1 ; tx += ad_data; // automatic type cast MOVLR 0 MOVFP ad_data,WREG MOVLR 1 ADDWF tx+1,1 MOVLR 0 MOVFP ad_data+1,WREG MOVLR 1 ADDWFC tx+2,1 ; ad_data = kp; // assign integer part MOVLR 2 MOVFP kp+1,WREG MOVLR 0 MOVWF ad_data MOVLR 2 MOVFP kp+2,WREG MOVLR 0 MOVWF ad_data+1 ; if ( tx < 0) MOVLR 1 BTFSS tx+2,7 GOTO m006 ; tx = -tx; // make positive COMF tx+2,1 COMF tx+1,1 COMF tx,1 INCF tx,1 MOVLW 0 ADDWFC tx+1,1 ADDWFC tx+2,1 ; av = tx/20.0; m006 MOVFP tx,WREG MOVLR 0 MOVWF arg1_3 MOVLR 1 MOVFP tx+1,WREG MOVLR 0 MOVWF arg1_3+1 MOVLR 1 MOVFP tx+2,WREG MOVLR 0 MOVWF arg1_3+2 CLRF arg2_3,1 MOVLW 20 MOVWF arg2_3+1 CLRF arg2_3+2,1 BSF 0x03,PA0 CALL _xdiv16_8 MOVLR 1 MOVWF av MOVLR 0 MOVFP arg1_3+1,WREG MOVLR 1 MOVWF av+1 MOVLR 0 MOVFP arg1_3+2,WREG MOVLR 1 MOVWF av+2 ; //mg = av * 1.25; ; //a = mg * 0.98; // 0.980469: error on constant: 0.000478 ; prev = vx; MOVFP vx,WREG MOVLR 2 MOVWF prev MOVLR 1 MOVFP vx+1,WREG MOVLR 2 MOVWF prev+1 MOVLR 1 MOVFP vx+2,WREG MOVLR 2 MOVWF prev+2 ; vx = a/5.0 + prev; MOVLR 1 MOVFP a,WREG MOVLR 0 MOVWF arg1_3 MOVLR 1 MOVFP a+1,WREG MOVLR 0 MOVWF arg1_3+1 MOVLR 1 MOVFP a+2,WREG MOVLR 0 MOVWF arg1_3+2 CLRF arg2_3,1 MOVLW 5 MOVWF arg2_3+1 CLRF arg2_3+2,1 CALL _xdiv16_8 MOVLR 2 MOVFP prev,WREG MOVLR 0 ADDWF arg1_3,W MOVLR 1 MOVWF vx MOVLR 2 MOVFP prev+1,WREG MOVLR 0 ADDWFC arg1_3+1,W MOVLR 1 MOVWF vx+1 MOVLR 2 MOVFP prev+2,WREG MOVLR 0 ADDWFC arg1_3+2,W MOVLR 1 MOVWF vx+2 ; ; // kp = vx * 0.036; // 0.03515626: error on constant: 0.024 ; kp = vx / (1.0/0.036); // 27.7773437 error on constant: 0.0000156 MOVFP vx,WREG MOVLR 0 MOVWF arg1_3 MOVLR 1 MOVFP vx+1,WREG MOVLR 0 MOVWF arg1_3+1 MOVLR 1 MOVFP vx+2,WREG MOVLR 0 MOVWF arg1_3+2 MOVLW 199 MOVWF arg2_3 MOVLW 27 MOVWF arg2_3+1 CLRF arg2_3+2,1 CALL _xdiv16_8 BCF 0x03,PA0 MOVLR 2 MOVWF kp MOVLR 0 MOVFP arg1_3+1,WREG MOVLR 2 MOVWF kp+1 MOVLR 0 MOVFP arg1_3+2,WREG MOVLR 2 MOVWF kp+2 ;} SLEEP GOTO main END ; *** KEY INFO *** ; 0x0001 P0 135 word(s) 1 % : main ; 0x2000 P1 60 word(s) 0 % : _xdiv16_8 ; RAM usage: 35 bytes (12 local), 867 bytes free ; Maximum call level: 1 ; Codepage 0 has 136 word(s) : 1 % ; Codepage 1 has 60 word(s) : 0 % ; Total of 196 code words (1 %)