TITLE "tune.asm: chromatic tuning fork, @4.000MHz" LIST p=16C71 ERRORLEVEL 0, -302 ; Key functions: ; -- device is off: turn on and show battery state ; -- press once: play selected note ; -- press again within 1 second: select next note ; -- power off when key idle for 5 minutes ; PIC16C71 connections: ; ; ********** ********** ; * *** * ; key A2 ** 1 18 ** A1 nf in ; * * ; speaker A3 ** 2 17 ** A0 ; * * ; A4 ** 3 16 ** Xin xtal ; * * ; pullup MCLR ** 4 15 ** Xout xtal ; * * ; GND ** 5 14 ** VCC ; * * ; power B0 ** 6 13 ** B7 led ; * * ; led B1 ** 7 12 ** B6 led ; * * ; led B2 ** 8 11 ** B5 led ; * * ; led B3 ** 9 10 ** B4 led ; * PIC16C71 * ; *********************** ; Supply circuit: ; ; BAT ----+----+-------------------------+ ; | | | ; | O | 10K |-S ; KEY <-| +------/\/\/-----+-----G| BS250 ; | O | |-D ; | 10K | | ; +--/\/\/--------+ | | ; | | | | ; | 10K | | | ----- ; +--/\/\/--+ | | +--|78L05|--+--- VCC ; | | | | ----- | ; | | | | | | ; A2 ---------------+ | | | 10u | | 10u ; | | | --- | --- ; 10K | | | --- | --- ; GND -------/\/\/--+ | | | | | ; | | | | | ; 10K | |-D | | | ; B0 --------/\/\/--------+--G| BS170 | | | ; |-S | | | ; | | | | ; GND --------------------------+--------+-----+-----+--- GND ; Audio circuit: ; ; ; 5V --+--------+ ; | | ; | / low pass ; | 100K \ ; | / mic amp +-------+--------+ ; | | | | . | ; | 100n | . --- 10n | |`. | ; --- || | |`. --- +-|- `. | ; mic ( )---||--+-----|+ `. 10K | 10K | >-+-- nf ; --- || | | >---+-/\/\/-+-/\/\/-+-|+ ,' ; | | +-|- ,' | | |,' ; | | | |,' | | ' ; | / | ' 270K | | ; | 100K \ +----/\/\/-+ --- 4n7 ; | / | --- ; | | / | ; | | \ 1K | ; | | / | ; | | | | ; | | --- 4u7 | ; | | --- | ; | | | | --- /| ; GND -+--------+---+--------------------------+---| |/ | ; | | ; || 10u 180R | | ; speaker ----------------||-------/\/\/-----------| |\ | ; || --- \| ; LEDs: ; 180R A ; B1 ------/\/\/-----+------>|------ B4 ; | A# ; +------>|------ B5 ; | B ; +------>|------ B6 ; | C ; +------>|------ B7 ; 180R C# ; B2 ------/\/\/-----+------>|------ B4 ; | D ; +------>|------ B5 ; | D# ; +------>|------ B6 ; | E ; +------>|------ B7 ; 180R F ; B2 ------/\/\/-----+------>|------ B4 ; | F# ; +------>|------ B5 ; | G ; +------>|------ B6 ; | G# ; +------>|------ B7 __IDLOCS H'ABCD' __CONFIG H'3FF9' ; WDT off, XT osc RTCC EQU 1 PC EQU 2 STATUS EQU 3 PORTA EQU 5 PORTB EQU 6 ADCON0 EQU H'08' ADRES EQU H'09' PCLATH EQU H'0A' INTCON EQU H'0B' _OPTION EQU H'81' ; OPTION register in page 1 _TRISA EQU H'85' ; TRISA in page 1 _TRISB EQU H'86' ; TRISB in page 1 _ADCON1 EQU H'88' ; ADCON1 in page 1 C EQU 0 DC EQU 1 Z EQU 2 P EQU 5 PON EQU B'11110001' ; all leds off, power on POFF EQU B'11110000' ; all leds off, power off tmp EQU H'0C' ; temporary storage tmrx EQU H'0D' ; timer for tone selection tmr0 EQU H'0E' ; auto power off timer * 65536us tmr1 EQU H'0F' ; auto power off timer * 16.78s ares EQU H'10' ; temporary storage for ad result smpl EQU H'11' ; last a/d sample tune EQU H'12' ; currently selected tone 0..11 step EQU H'13' ; current led for tuning monitor dkey EQU H'14' ; debouncing of key switch ORG 0 ; reset GOTO main ORG H'08' main CALL Init MOVLW B'11110001' ; internal osc, channel 2, power on MOVWF ADCON0 CALL battery ; display battery voltage CALL pwron CLRF RTCC ; reset rtcc and overflow flag BCF INTCON,2 CLRF tune ; select tone 'A' CLRF step MOVLW H'80' ; disable first key hit MOVWF dkey MOVLW D'16' ; tone selection display about 1s MOVWF tmrx loop CALL tone GOTO loop ORG H'20' Init MOVLW B'00010111' ; speaker off MOVWF PORTA MOVLW PON ; power on MOVWF PORTB MOVLW B'00001' ; PCLATH to data range MOVWF PCLATH BSF STATUS,P ; set page 1 MOVLW H'FF' ; reserved for corrections MOVLW B'11010111' ; rtc prescaler 256 MOVWF _OPTION MOVLW B'00010111' ; 3 output 4,2,1,0 inputs MOVWF _TRISA MOVLW B'00000000' ; outputs 7..1 led mux, 0 power MOVWF _TRISB BCF STATUS,P ; set page 0 RETLW 0 ORG H'40' pwron MOVLW PON ; 3 set power on, timer to 5 min MOVWF PORTB ; 4 MOVLW D'17' ; 5 17 x 16.78s MOVWF tmr1 ; 6 MOVLW D'226' ; 7 + 226 x 65536 us MOVWF tmr0 ; 8 RETLW 0 ; 10 pwroff MOVLW POFF ; power off MOVWF PORTB SLEEP ; bye bye SLEEP SLEEP SLEEP SLEEP ORG H'50' battery CALL dly100 ; 129 CALL dly20 ; 149 CALL dly24 ; 173 BCF ADCON0,1 ; 173 reset int flag BSF ADCON0,2 ; 175 start a/d conversion CALL dly100 ; 275 wait for result CALL dly100 ; 375 MOVF ADRES,W ; 376 get result MOVWF ares ; 377 BCF PORTA,3 ; 378 speaker off CLRF step ; 379 MOVLW PON ; 380 leds off MOVWF PORTB ; 381 BTFSS ares,7 ; 382 key pressed if ch2 >= 2.5V RETLW 0 ; key released: done MOVLW D'160' ; 384 SUBWF ares,F ; 385 ch2 >= 3.125V (bat >= 6.25V) BTFSS STATUS,C ; 386 CLRF ares ; 387 no: all leds off bat1 CALL speaker ; 12 give an 'a' 12 * 378 + 9 us MOVF step,W ; 13 MOVF ares,F ; 14 ares zero? BTFSC STATUS,Z ; 15 MOVLW D'12' ; 16 yes: no led CALL led ; 22 MOVWF PORTB ; 23 INCF step,F ; 24 select next step MOVF step,W ; 25 XORLW D'12' ; 26 step = 12? BTFSC STATUS,Z ; 27 GOTO battery ; 29 yes: new measurement MOVLW D'8' ; 29 SUBWF ares,F ; 30 light next led? BTFSS STATUS,C ; 31 CLRF ares ; 32 no: all leds off CALL dly100 ; 132 CALL dly100 ; 232 CALL dly100 ; 332 CALL dly20 ; 352 CALL dly24 ; 376 GOTO bat1 ; 378 loop to next step ORG H'80' ; this procedure is called 12 times per tone period, call total: 193us cycle CALL dly50 ; 52 MOVF ADRES,W ; 53 save ad result MOVWF ares ; 54 MOVLW B'11110001' ; 55 conversion on ch2 MOVWF ADCON0 ; 56 BSF ADCON0,2 ; 57 start CALL dly20 ; 77 CALL dly20 ; 97 CALL dly12 ; 109 GOTO sampl1 ; 111 ORG H'90' sampl1 MOVF tmrx,F ; 1 tone selection or tuning mode? BTFSC STATUS,Z ; 2 GOTO sampl2 ; 4 tuning monitor MOVLW D'12' ; 4 tone selection display MOVF step,F ; 5 BTFSC STATUS,Z ; 6 MOVF tune,W ; 7 led on if at step 0 CALL led ; 13 MOVWF PORTB ; 14 CALL speaker ; 26 GOTO sampl4 ; 28 sampl2 BCF PORTA,3 ; 5 speaker off DECF ares,W ; 6 get a/d result - 1 SUBWF smpl,W ; 7 BTFSS STATUS,C ; 8 carry clear if (ADRES-1) > smpl GOTO sampl3 ; 10 MOVLW PON ; 10 no led MOVWF PORTB ; 11 CALL dly15 ; 26 GOTO sampl4 ; 28 sampl3 MOVF step,W ; 11 CALL led ; 17 MOVWF PORTB ; 18 CALL dly10 ; 28 sampl4 DECF step,F ; 29 step down MOVLW D'11' ; 30 BTFSC step,7 ; 31 MOVWF step ; 32 NOP ; 33 MOVF ares,W ; 34 store current a/d result MOVWF smpl ; 35 timer BTFSS INTCON,2 ; 1 check rtcc: skip if overflow set GOTO timer1 ; 3 BCF INTCON,2 ; 3 clear overflow flag MOVF tmrx,F ; 4 decrement tmrx if > 0 BTFSS STATUS,Z ; 5 DECF tmrx,F ; 6 DECFSZ tmr0,F ; 7 decrement power off timer GOTO timer2 ; 9 MOVF tmr1,F ; 9 power off if tmr1 zero BTFSC STATUS,Z ; 10 GOTO pwroff ; 12 DECF tmr1,F ; 12 else decrement tmr1 GOTO keypol ; 14 timer1 CALL dly6 ; 9 timer2 CALL dly5 ; 14 keypol MOVF ADRES,W ; 1 MOVWF ares ; 2 MOVLW B'11101001' ; 3 conversion on ch1 MOVWF ADCON0 ; 4 BSF ADCON0,2 ; 5 start MOVLW D'154' ; 6 key pressed if ch2 > 3.0V SUBWF ares,W ; 7 BTFSS STATUS,C ; 8 GOTO keypol3 ; 10 key released INCF dkey,F ; 10 key pressed MOVF dkey,W ; 11 XORLW H'80' ; 12 accept key if dkey is 0x80 BTFSS STATUS,Z ; 13 GOTO keypol1 ; 15 CALL pwron ; 25 reset power off timer MOVF tmrx,F ; 26 tone selection or tuning mode? BTFSC STATUS,Z ; 27 GOTO keypol2 ; 29 stay at same tone and redisplay INCF tune,F ; select next halftone MOVF tune,W ; XORLW D'12' ; tune mod 12 BTFSC STATUS,Z ; CLRF tune ; CLRF step ; RETLW 1 ; keypol1 BTFSS dkey,7 ; 16 dkey saturation at 0x80 GOTO dly17 ; 33 return from there MOVLW H'80' ; 18 MOVWF dkey ; 19 CALL dly10 ; 29 keypol2 MOVLW D'16' ; 30 tone selection display about 1s MOVWF tmrx ; 31 RETLW 0 ; 33 keypol3 CLRF dkey ; 11 clear dkey if key not pressed CALL dly20 ; 31 RETLW 0 ; 33 dly100 MOVLW D'31' ; 3 MOVWF tmp ; 4 dly100a DECFSZ tmp,F ; 31 * 3 - 1 GOTO dly100a GOTO dly4 ; 100 dly50 MOVLW D'15' ; 3 MOVWF tmp ; 4 dly50a DECFSZ tmp,F ; 15 * 3 - 1 GOTO dly50a RETLW 0 ; 50 dly25 NOP ; call total: 25 dly24 NOP ; call total: 24 dly23 NOP ; call total: 23 dly22 NOP ; call total: 22 dly21 NOP ; call total: 21 dly20 NOP ; call total: 20 dly19 NOP ; call total: 19 dly18 NOP ; call total: 18 dly17 NOP ; call total: 17 dly16 NOP ; call total: 16 dly15 NOP ; call total: 15 dly14 NOP ; call total: 14 dly13 NOP ; call total: 13 dly12 NOP ; call total: 12 dly11 NOP ; call total: 11 dly10 NOP ; call total: 10 dly9 NOP ; call total: 9 dly8 NOP ; call total: 8 dly7 NOP ; call total: 7 dly6 NOP ; call total: 6 dly5 NOP ; call total: 5 dly4 RETLW 0 ; call total: 4 TA CALL cycle ; 220.00Hz = 12 * 378 + 9 us XORLW 0 ; 194 BTFSS STATUS,Z ; 195 RETLW 0 ; CALL dly100 ; +100 CALL dly50 ; +50 CALL dly20 ; +20 CALL dly8 ; +8 MOVF step,F ; 197 BTFSS STATUS,Z ; 198 GOTO TA ; 200 CALL dly8 ; +8 GOTO TA ; +1 TA# CALL cycle ; 233.08Hz = 12 * 357 + 6 us XORLW 0 ; 194 BTFSS STATUS,Z ; 195 RETLW 0 ; CALL dly100 ; +100 CALL dly50 ; +50 CALL dly7 ; +7 MOVF step,F ; 197 BTFSS STATUS,Z ; 198 GOTO TA# ; 200 CALL dly5 ; +5 GOTO TA# ; +1 TB CALL cycle ; 246.94Hz = 12 * 337 + 6 us XORLW 0 ; 194 BTFSS STATUS,Z ; 195 RETLW 0 ; CALL dly100 ; +100 CALL dly20 ; +20 CALL dly17 ; +17 MOVF step,F ; 197 BTFSS STATUS,Z ; 198 GOTO TB ; 200 CALL dly5 ; +5 GOTO TB ; +1 TC CALL cycle ; 261.63Hz = 12 * 318 + 6 us XORLW 0 ; 194 BTFSS STATUS,Z ; 195 RETLW 0 ; CALL dly100 ; +100 CALL dly18 ; +18 MOVF step,F ; 197 BTFSS STATUS,Z ; 198 GOTO TC ; 200 CALL dly5 ; +5 GOTO TC ; +1 TC# CALL cycle ; 277.18Hz = 12 * 300 + 8 us XORLW 0 ; 194 BTFSS STATUS,Z ; 195 RETLW 0 ; CALL dly100 ; +100 MOVF step,F ; 197 BTFSS STATUS,Z ; 198 GOTO TC# ; 200 CALL dly7 ; +7 GOTO TC# ; +1 TD CALL cycle ; 293.66Hz = 12 * 283 + 9 us XORLW 0 ; 194 BTFSS STATUS,Z ; 195 RETLW 0 ; CALL dly50 ; +50 CALL dly20 ; +20 CALL dly13 ; +13 MOVF step,F ; 197 BTFSS STATUS,Z ; 198 GOTO TD ; 200 CALL dly8 ; +8 GOTO TD ; +1 TD# CALL cycle ; 311.13Hz = 12 * 267 + 10 us XORLW 0 ; 194 BTFSS STATUS,Z ; 195 RETLW 0 ; CALL dly50 ; +50 CALL dly17 ; +17 MOVF step,F ; 197 BTFSS STATUS,Z ; 198 GOTO TD# ; 200 CALL dly9 ; +9 GOTO TD# ; +1 TE CALL cycle ; 329.63Hz = 12 * 252 + 10 us XORLW 0 ; 194 BTFSS STATUS,Z ; 195 RETLW 0 ; CALL dly50 ; +50 GOTO $+1 ; +2 MOVF step,F ; 197 BTFSS STATUS,Z ; 198 GOTO TE ; 200 CALL dly9 ; +9 GOTO TE ; +1 TF CALL cycle ; 349.23Hz = 12 * 238 + 7 us XORLW 0 ; 194 BTFSS STATUS,Z ; 195 RETLW 0 ; CALL dly20 ; +20 CALL dly18 ; +18 MOVF step,F ; 197 BTFSS STATUS,Z ; 198 GOTO TF ; 200 CALL dly6 ; +6 GOTO TF ; +1 TF# CALL cycle ; 369.99Hz = 12 * 225 + 3 us XORLW 0 ; 194 BTFSS STATUS,Z ; 195 RETLW 0 ; CALL dly25 ; +25 MOVF step,F ; 197 BTFSS STATUS,Z ; 198 GOTO TF# ; 200 GOTO $+1 ; +2 GOTO TF# ; +1 TG CALL cycle ; 392.00Hz = 12 * 212 + 7 us XORLW 0 ; 194 BTFSS STATUS,Z ; 195 RETLW 0 ; CALL dly12 ; +12 MOVF step,F ; 197 BTFSS STATUS,Z ; 198 GOTO TG ; 200 CALL dly6 ; +6 GOTO TG ; +1 TG# CALL cycle ; 415.30Hz = 12 * 200 + 8 us XORLW 0 ; 194 BTFSS STATUS,Z ; 195 RETLW 0 ; MOVF step,F ; 197 BTFSS STATUS,Z ; 198 GOTO TG# ; 200 CALL dly7 ; +7 GOTO TG# ; +1 ORG H'1C0' tone MOVLW B'00001' ; PCLATH to data range MOVWF PCLATH MOVF tune,W ADDWF PC,F ; jump to selected tune routine GOTO TA ; 220.00Hz = 12 * 378 + 9 us GOTO TA# ; 233.08Hz = 12 * 357 + 6 us GOTO TB ; 246.94Hz = 12 * 337 + 6 us GOTO TC ; 261.63Hz = 12 * 318 + 6 us GOTO TC# ; 277.18Hz = 12 * 300 + 8 us GOTO TD ; 293.66Hz = 12 * 283 + 9 us GOTO TD# ; 311.13Hz = 12 * 267 + 10 us GOTO TE ; 329.63Hz = 12 * 252 + 10 us GOTO TF ; 349.23Hz = 12 * 238 + 7 us GOTO TF# ; 369.99Hz = 12 * 225 + 3 us GOTO TG ; 392.00Hz = 12 * 212 + 7 us GOTO TG# ; 415.30Hz = 12 * 200 + 8 us led ADDWF PC,F ; (6us) return pattern to light a led RETLW B'01111001' ; LED 0 RETLW B'10111001' ; LED 1 RETLW B'11011001' ; LED 2 RETLW B'11101001' ; LED 3 RETLW B'01110101' ; LED 4 RETLW B'10110101' ; LED 5 RETLW B'11010101' ; LED 6 RETLW B'11100101' ; LED 7 RETLW B'01110011' ; LED 8 RETLW B'10110011' ; LED 9 RETLW B'11010011' ; LED 10 RETLW B'11100011' ; LED 11 RETLW PON ; NO LED speaker MOVLW B'00001' ; (12us) PCLATH to data range MOVWF PCLATH ; MOVF step,W ; ADDWF PC,F ; speaker on for steps 0-2 and 6-8 GOTO spkron ; 0 GOTO spkron ; 1 GOTO spkron ; 2 GOTO spkroff ; 3 GOTO spkroff ; 4 GOTO spkroff ; 5 GOTO spkron ; 6 GOTO spkron ; 7 GOTO spkron ; 8 GOTO spkroff ; 9 GOTO spkroff ; 10 GOTO spkroff ; 11 spkron BSF PORTA,3 ; on RETLW 0 ; spkroff BCF PORTA,3 ; off RETLW 0 ; END ;