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