Tuner.txt by David Thomas
and example PIC project

Example Guitar Tuner from David Thomas' PIC Programs by David B. Thomas.




		DEVICE PIC16C54,HS_OSC,WDT_OFF,PROTECT_OFF

audio		equ	RA.0
low_led		equ	RA.1
high_led	equ	RA.2
right_led	equ	RA.3

new_state	equ	09h
curr_state	equ	0ah
count_hi	equ	0bh
count_lo	equ	0ch
zflag		equ	0dh.0
lo		equ	0eh
hi		equ	0fh
temp		equ	10h
accum_l		equ	11h
accum_m		equ	12h
accum_h		equ	13h
sample_no	equ	14h


		RESET	Start

;
; Clock: 16 MHz.  RTCC 4MHz prescaled by 32: 125 KHz.
; Counts are RTCC/Hz

; CENTER FREQUENCIES

ECTR		equ	379	; High E	329.6 Hz
BCTR		equ	506	; B		246.9 Hz
GCTR		equ	638	; G		196.0 Hz
DCTR		equ	852	; D		146.8 Hz
ACTR		equ	1136	; A		110.0 Hz
LECTR		equ	1517	; low E		 82.4 Hz
LDCTR		equ	1703	; low D		 73.4 Hz

; half step flat centers
EbCTR		equ	402	; High Eb	311.1 Hz
BbCTR		equ	536	; Bb		233.1 Hz
GbCTR		equ	676	; Gb		185.0 Hz
DbCTR		equ	902	; Db		138.6 Hz
AbCTR		equ	1204	; Ab		103.8 Hz
LEbCTR		equ	1607	; low Eb	 77.8 Hz
LDbCTR		equ	1804	; low Db	 69.3 Hz

; TRANSITION FREQUENCIES (log center between strings)

ETOB		equ	438	; E to B	285.3 Hz
BTOG		equ	568	; B to G	220.0 Hz
GTOD		equ	737	; G to D	169.6 Hz
DTOA		equ	984	; D to A	127.1 Hz
ATOE		equ	1313	; A to E	 95.2 Hz
ETOD		equ	1607	; E to D	 77.8 Hz

; half step flat transitions

ETOBb		equ	464	; Eb to Bb	269.3 Hz
BTOGb		equ	602	; Bb to Gb	207.7 Hz
GTODb		equ	781	; Gb to Dd	160.1 Hz
DTOAb		equ	1043	; Db to Ab	119.9 Hz
ATOEb		equ	1390	; Ab to Eb	 89.9 Hz
ETODb		equ	1703	; Eb to Db	 73.4 Hz

Get_ctr_lo	jmp	PC+W
		retw	ECTR>,BCTR>,GCTR>,DCTR>,ACTR>,LECTR>,LDCTR>
Get_ctr_hi	jmp	PC+W
		retw	ECTR<,BCTR<,GCTR<,DCTR<,ACTR<,LECTR<,LDCTR<
Get_x_lo	jmp	PC+W
		retw	ETOB>,BTOG>,GTOD>,DTOA>,ATOE>,ETOD>,0
Get_x_hi	jmp	PC+W
		retw	ETOB<,BTOG<,GTOD<,DTOA<,ATOE<,ETOD<,0

Start
		mov	!RB,#00000000b
		mov	!RA,#0001b
		mov	OPTION,#00000100b
		clr	new_state
		clr	curr_state
		clr	count_hi
		clr	count_lo
		clrb	low_led
		setb	high_led
		clrb	right_led
		setb	zflag
		clr	accum_l
		clr	accum_m
		clr	accum_h
		mov	RTCC,#1

BigLoop
		mov	sample_no,#64
Loop
		mov	W,RTCC
		test	W
		jnz	Rt_nonzero

		; RTCC is zero.
		jb	zflag,Sample

		setb	zflag
		inc	count_hi
		mov	W,count_hi
		and	W,#10000000b
		jz	Sample

		; count_hi too high -- there's NOTHING happenin'!
		clrb	low_led
		clrb	high_led
		clrb	right_led
		jmp	Sample

Rt_nonzero
		clrb	zflag

Sample
		; sample the input pin
		clr	new_state
		addb	new_state,audio

		mov	W,curr_state
		xor	W,new_state
		jz	Loop

		; we have a new state
		mov	curr_state,new_state
		test	curr_state
		jz	Loop	; ignore 1->0 transitions

		; we have a 0->1 transition
		mov	count_lo,RTCC
		clr	RTCC

		; add count to accumulator
		add	accum_l,count_lo
		addb	accum_m,C
		add	accum_m,count_hi
		addb	accum_h,C

		setb	zflag
		clr	count_hi
		djnz	sample_no,Loop	; wait till we have 64 samples

		; we have accumulated the sum of 64 samples.  Divide by
		; 64 the fun-n-easy way (right shift by 6 bits!)

		rr	accum_h
		rr	accum_m
		rr	accum_l

		rr	accum_h
		rr	accum_m
		rr	accum_l

		rr	accum_h
		rr	accum_m
		rr	accum_l

		rr	accum_h
		rr	accum_m
		rr	accum_l

		rr	accum_h
		rr	accum_m
		rr	accum_l

		rr	accum_h
		rr	accum_m
		rr	accum_l

		mov	count_lo,accum_l
		mov	count_hi,accum_m

		; determine which string we think this is
		mov	temp,#0
FindLoop
		mov	W,temp		; get transition value
		call	Get_x_hi
		mov	hi,W
		mov	W,temp
		call	Get_x_lo
		mov	lo,W

		or	W,hi		; end of table?
		jz	FoundString	; if so, assume lowest note

		sub	lo,count_lo	; compare with this value
		subb	hi,C
		sub	hi,count_hi
		rl	hi
		jnc	FoundString	; if count was smaller, this is it

		inc	temp		; loop and try next string
		jmp	FindLoop

FoundString
		; temp now has value of string found
		mov	W,temp
		call	Get_ctr_hi
		mov	hi,W
		mov	W,temp
		call	Get_ctr_lo
		mov	lo,W

		sub	lo,count_lo
		subb	hi,C
		sub	hi,count_hi

		mov	W,hi
		or	W,lo
		jz	JustRight
		rl	hi
		jnc	TooLow
		jmp	TooHigh

JustRight
		clrb	low_led
		clrb	high_led
		setb	right_led
		jmp	Bottom

TooLow
		setb	low_led
		clrb	high_led
		clrb	right_led
		jmp	Bottom

TooHigh
		clrb	low_led
		setb	high_led
		clrb	right_led

Bottom
		clr	accum_l
		clr	accum_m
		clr	accum_h
		jmp	BigLoop