2-D interpolation for HC11
Andrew Dennison
ADEN at mechman.mm.swin.edu.au
Fri Sep 22 02:46:27 GMT 1995
> Yes, I will take a copy - I am sure can use it.
Ok. It's at the end of this post.
>
> Researching into the 2-D interpolation problem, the "cleanest"
> algorithm that I have found to date is in the Handbook of
> Mathematical Functions by Abramowitz and Stegun, which uses
> the 4-point method:
>
> f(x0+ph, y0+qk) = (1-p) * (1-q) * f(0,0) + p * (1-q) * f(1,0) +
> (1-p) * q * f(0,1) + p * q * f(1,1)
> with:
> x0, y0 = some arbitrary baseline (D.C. offset)
> p = normalized 1st coordinate value (ranging from 0 to 1)
> p = normalized 2nd coordinate value (ranging from 0 to 1)
> f(0,0) = function value at grid point coordinate (0,0)
> f(0,1) = function value at grid point coordinate (0,1)
> f(1,0) = function value at grid point coordinate (1,0)
> f(1,1) = function value at grid point coordinate (1,1)
>
> There are 5, 6, and 7 point formulas as well, but more complicated.
>
> Anyone out there know of anything else more suited for
> integer or fixed-point math?
My code does most of it's calculations in fractions, ie 0 -> 0xFFFF
is 0 to 1. You use the same basic algorithms as floating point except
scale your data to use the dynamic range of your integers (while
avoiding overflows).
This code was used to calculate the required position of a stepper
motor based on the duty cycle of a fuel injector. The map has 16
equispaces elements but can be easily hacked for 8, 16, 32, 64, etc.
These are the global variables the code manipulates:
short Stepper_Desired_Position; /* output from interpolation*/
unsigned short Injector_Duty_Cycle; /* input variable */
unsigned short Injector_Map [16]; /* 16 element table */
char Current_Map_Index; /* the data point currently being used */
/*************************** Table Interpolate *****************************/
/** This function uses the Injector Duty Cycle to calculate the required **/
/** stepper motor position. **/
/***************************************************************************/
void Table_Interpolate ()
{
#asm
;register unsigned char Index;
;Index = (unsigned char) Injector_Duty_Cycle / 0x1000;
ldd _Injector_Duty_Cycle
ldx #1000h
idiv
xgdx ;Index in ACCB
;if (Index == 0)
subb #0 ;Test ACCB
bne t_else
stab _Current_Map_Index ;for map adjustment
;Stepper_Desired_Position = Injector_Map [0] * (Injector_Duty_Cycle & 0x0FFF) / 0x0FFF;
ldd _Injector_Duty_Cycle
anda #15 ;mask with 0x0FFF
ldx #0FFFh
fdiv ;Duty * 2^16 / 0x0FFF
xgdx ;get fraction in D
ldab _Injector_Map+1 ;ls byte of Injector_Map[0]
mul ;ms byte of fraction in a
tab ;keep ms byte of result
clra ;extend to 16 bits
std _Stepper_Desired_Position
jmp t_end
;else
;Stepper_Desired_Position = Injector_Map [Index-1] +
;((Injector_Map [Index] - Injector_Map [Index-1]) *
;(Injector_Duty_Cycle & 0x0FFF) / 0x0FFF);
t_else
ldx #_Injector_Duty_Cycle
brclr 0,x, 08h, t1
stab _Current_Map_Index ;Closest data point is Index
addb #-1
bra t2
t1 addb #-1
stab _Current_Map_Index ;Closest data point is Index-1
t2 clra
asld ;Index * 2 for 16 bit table
addd #_Injector_Map
std ctemp ;save pointer to Injecter_Map [Index-1]
ldd _Injector_Duty_Cycle
anda #15 ;mask with 0x0FFF
ldx #0FFFh
fdiv ;Duty * 2^16 / 0x0FFF
pshx ;save fraction on stack
ldx ctemp
ldd 2,X ;Get Injector_Map [Index]
subd 0,X ;subtract Injector_Map [Index-1]
staa ctemp ;sign extended part (0x00 or 0xFF)
pula ;get high byte of fraction
bgt t3 ;if subd result was positive
negb ;else subd result was negative
mul ;b is unsigned map difference
nega ;make ms byte of result -ve again
bra t4 ;end of else
t3 mul ;b contains low byte of map difference
t4 tab ;keep ms byte of result
ldaa ctemp ;sign extend to 16 bits
addd 0,X ;add Injector_Map [Index-1]
std _Stepper_Desired_Position
pulb ;remove the rest of x from stack
t_end
#endasm
}
Andrew
------------------------------------
Andrew Dennison - Research Associate
The CIM Centre Address: CIM Centre
Melbourne, AUSTRALIA Swinburne University
Phone: +61 3 9214 8296 PO Box 218
Fax: +61 3 9819 4949 Hawthorn Victoria 3122
WWW: http://cim.mm.swin.edu.au/ Australia
More information about the Diy_efi
mailing list