;From Peter Hemsley 15July01

Peter says that "This is too good to miss, although it's probably not for the faint hearted. Of course it's easier to do the whole lot as a 256 byte look-up table, but this was not really an option until PICs came with larger memories".

;Linearise a non linear input by look-up table and linear interpolation
;For non linear devices such as thermistors,ldr's etc
;May also be used to generate non linear functions such as sine,cos,exp,log etc
;w -> f(w)

	processor 16f84
	include p16f84.inc

temp1	equ	0x0C
temp2	equ	0x0D
X1	equ	0X0E
x2	equ	0x0F
test	equ	0x10

	org	0		;Test code for MPLAB simulator
	clrf	test
loop	movf	test,w
	call	linearise
brk1	incfsz	test
	goto	loop
brk2	return


linearise
	movwf	temp1
	andlw	0x0F		;extract interpolation factor (lower nibble)
	movwf	temp2

	swapf	temp1,w		;extract look-up table index (upper nibble)
	andlw	0x0F
	addlw	1
	movwf	temp1

	call	functbl		;get index+1
	movwf	x2
	decf	temp1,w
	call	functbl		;get index
	movwf	x1
	subwf	x2,w

	rrf	x2		;save carry
	skpc			;carry set=positive slope
	sublw	0		;slope is negative

	clrf	temp1		;clear result
	bsf	temp1,3		;add 0.5 for rounding
	setc			;flag bit to loop four times
mloop	rrf	temp2		;multiply temp2 and w
	skpnc
	addwf	temp1
	rrf	temp1		;divide by two
	btfss	temp2,4		;test for flag bit
	goto	mloop

	movf	temp1,w
	btfsc	x2,7
	addwf	x1,w		;slope was positive
	btfss	x2,7
	subwf	x1,w		;slope was negative
	return			;result in w

functbl
	addwf	pcl		;cosine as an example (easy to verify result)
	retlw	D'255'		;0 deg
	retlw	D'254'
	retlw	D'250'
	retlw	D'244'
	retlw	D'236'
	retlw	D'225'
	retlw	D'212'
	retlw	D'197'
	retlw	D'180'		;45 deg
	retlw	D'162'
	retlw	D'142'
	retlw	D'120'
	retlw	D'98'
	retlw	D'74'
	retlw	D'50'
	retlw	D'25'
	retlw	D'0'		;90 deg

	end

