Interpolation
Kevin Timmerman
opossum at macatawa.org
Mon Apr 13 23:29:35 GMT 1998
> <thormj at iname.com> wrote:
> > Solution #2:
> > Can anyone provide me with a *quick* 2 point linear interpolation
> > (1d map)... and a quick 4 point interpolation (2d map)?
> >
> > My current code looks like:
> > return (x-curve[i-1].x)*(curve[i].y - curve[i-1].y)/
> > (curve[i].x - curve[i-1].x) + curve[i-1].y;
> >
> > This is for a 68hc11 uC, so the less math the better. :-/
Here is some 68HC11 asm code from Bosch/VW Digifant ECU.....
*--------------------------------------------------------------
*
* Simple table lookup for 16 byte table
*
* Entry: B - Index ( 0 to $FF )
* X - Table address
*
* Exit: B - Lookup value
* X - Points to lookup value
*
tbl_lu LSRB
LSRB
LSRB
LSRB
ABX
LDAB ,X
RTS
*--------------------------------------------------------------
* Interpolated table lookup
*
* Entry: B - Table index
* 0 - $F0 for 16 byte table
* 0 - $FF for 17 byte table
* X - Table address
*
* Exit: B - Interpolated table lookup
* A - Zero
* X - Address of uninterpolated value
*
tbl_itp PSHB ; Save index
LSRB ; Divide by 16
LSRB
LSRB
LSRB
ABX ; Adjust table pointer
PULB ; Restore index
JSR interp ; Interpolate
CLRA
RTS
*-------------------------------------------------------------------
*
* 2D interpolation of 16 * 16 table
*
* Entry: A - Table Y (row) 0 to $F0
* B - Table X (column) 0 to $FF
* X - Table address
*
* Exit: B - Interpolated result
* X - Trashed
* A - Trashed
*
interp2d ;4AC3
STAA tmp3 ; Save row
STAB tmp4 ; Save column
LSRB ; Divide column by 16
LSRB
LSRB
LSRB
STAB tmp1 ; Save column/16
LDAB tmp3 ; Get row
ANDB #$F0 ; Mask
ADDB tmp1 ; Add column
; B = row/16*16 + column/16
ABX ; Adjust table address
LDAA tmp3 ; Get row
LDAB tmp4 ; Get column
CMPA #$F0 ; Row at max ??
BCS row_ok ; 2D interpolate if not
LDAA #$F0 ; Limit row to $F0
CMPB #$F0 ; Column max ??
BNE LBL4AE6 ; 1D Interpolate if not
LDAB $00,X ; Get uninterpolated value
BRA LBL4AE9 ; Return
LBL4AE6 JSR interp ; Interpolate within row
LBL4AE9 BRA LBL4B10 ; Return
row_ok CMPB #$F0 ; Column max ???
BNE col_ok ; 1D interpolate if it is
LDAA ,X ; Get low
STAA tmp1 ; Save
LDAA $10,X ; Get high
STAA tmp2 ; Save
BRA LBL4B08 ; Interpolate...
col_ok JSR interp ; Interpolate row
STAB tmp1 ; Save
LDAB #$10 ; Next row
ABX
LDAB tmp4 ; Get column (for interp index)
JSR interp ; Interpolate row
STAB tmp2 ; Save
LBL4B08 LDAB tmp3 ; Get row (for interp index)
LDX #tmp1 ; Interpolate saved values
JSR interp
LBL4B10 RTS
*--------------------------------------------------------------
*
* Interpolation for 16 byte tables
*
* B = ( ( low * (16-index) ) + ( high * index ) ) / 16
*
* Entry: B - interpolation index, only lowest four bits used
* [X] - low value
* [X+1] - high value
*
* Exit: B - interpolated value
* A - zero (trashed)
*
interp
ANDB #$0F ; Use only lowest four bits
PSHB ; Save for later
LDAA 1,X ; Get high
MUL ; high * index
PSHB ; Save
PSHA
LDAA ,X ; Get low
PSHX ; Save X
TSX ; S -> X
LDAB 4,X ; Get saved index off stack
SUBB #$10 ; index = 16 - index
NEGB
MUL ; low * (16 - index)
ADDD 2,X ; Add low*(16-index) to (high*index) from stack
ADDD #$0008 ; Rounding
LSRD ; Divide by 16
LSRD
LSRD
LSRD
PULX ; Restore X
INS ; Cleanup stack
INS
INS
RTS
More information about the Diy_efi
mailing list