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