FSM_audio.asm
;Ver. 1.0  20120226
;Johnny Apell/SM7UCZ
;
;Program made in MPLAB IDE v8.83
;
;Program for Field Strength Meter with audio FSM output and sidetone
;
;Intern RC-clock 4MHz , no watchdog 


;**********************************************************************************
;Register


Avalue		equ 20h				;analogvalue
temp		equ	21h				;
temp1		equ	22h				;"
count1		equ 23h
count2		equ 24h
count3		equ 25h
count4		equ 26h
count5		equ 27h
count6		equ 28h
count7		equ 29h
Flag		equ	3Ah				;helpflags

#define 	SpkrA			GPIO,0	
#define		SpkrB			GPIO,1
#define		test			GPIO,3
#define		LED				GPIO,5
#define		flag1			Flag,0
#define		flag2			Flag,1


;**********************************************************************************


;PIC processor 12F683

	list    p=12f683	;
	#include <p12f683.inc>  ; processor specific variable definitions
	__config _INTOSCIO & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF & _CP_ON & _CPD_OFF & _BOD_NSLEEP & _IESO_OFF & _FCMEN_OFF
	
					  		
	ERRORLEVEL -302 		; suppress message because of page change

;**********************************************************************************
	org     0	     		;adress at power on or reset
	goto    init    		;goto setup processor

	org		4				;interruptaddress
	goto	init

;**********************************************************************************


			;Reading analog input 8 bits
ANALOG
	bsf		LED				;start LED for biasing

	bsf		ADCON0,1		;start analog reading
	btfsc	ADCON0,1		;ready?
	goto	$-1				;no..loop back ?
	movfw	ADRESH			;load high bits result
	movwf   Avalue			;to register... for sidetone start/stopp
	movwf	CCPR1L			;and to PWM for meter

	movlw	.253			;Signal strength over 253...max make beeps!
	subwf	Avalue,w
	btfss	STATUS,C		;test if FSM is under 253
	bcf		flag2
	btfsc	STATUS,C		;test if FSM is over 253
	call	beeps			;FSM is max... call beeps

							;Signalstrength over 10...start sidetone
    movlw  .10     			;put the value to compare with in W... sidetone start
    subwf  Avalue,W  		;subtract W from the File Register
                            ;you want to compare with and put
                            ;result in W (this preserve file register)
    btfss  STATUS,C    		;Test for Carry Flag Clear
    call   OFF         		;Analog < CompTo ...  sidetone off
    btfsc  STATUS,C    		; Test for Carry Flag Set
    call   Speaker      	; Analog >= CompTo.... sidetone on
 
	return		

;********************************************************************************	
delayms
	    					;1 mS delay @ 4MHz
	movlw   0f9h			;249    sidetone pitch!
  	nop
	addlw   0ffh			;255
    btfss   STATUS,Z
    goto    $-2
    return
;************************************************************************************
delay
	btfss	flag1			;test if audio FSM or only sidetone on=only sidetone
	goto	$+4
	movlw	.255
	movwf	temp1
	goto	$+3
	movfw	Avalue
	movwf	temp1
	incfsz	temp1,f
	goto	$-1
	decfsz temp,f
	goto	$-1
	return

;*******************************************************************************
Speaker					;Sidetone
	btfss	SpkrA		;toggle speaker each time
	goto	$+4			
	bcf		SpkrA		
	bsf		SpkrB
	return
	bsf		SpkrA		;toggle speaker other way
	bcf		SpkrB

	clrf	count1		;reset sleepcounter...activity is going on
	clrf	count2
	movlw	.9			;OK for about 10 min before sleep
	movwf	count3

	return

;*******************************************************************************
OFF
	bcf		SpkrA		;speaker off.. save power
	bcf		SpkrB

	return
;********************************************************************************
Test					;for adjusting meter to max with trimmer
	call	delay		;debounce
	btfss	flag1		;toggle flag1  for audio FSM or not
	goto	$+3
	bcf		flag1
	goto	$+2
	bsf		flag1

	movlw	.255		;put out max to PWM
	movwf	CCPR1L

	movlw	.10			;time out if testbutton is pressed more than 2 sec
	movwf	temp1
	call	delayms
	decfsz	temp,f
	goto	$+4
	decfsz	temp1,f
	goto	$+2
	goto	sleeping	;shut off
	btfsc	test		;is test input on?
	goto	$-7
	clrf	CCPR1L		;off clear PWM
	movlw	.9			;OK for about 10 min before sleep
	movwf	count3
	return
;********************************************************************************
beeps
	btfsc	flag1		;no beeps if no audio FSM
	return
beeps1
	movlw	.3			; 3 beeps
	movwf	count5
	movlw	.25			;delay between beeps
	movlw	count7
jmp1
	call	Speaker		;make 3 beep before sleep
	call	delay
	decfsz	count4,f
	goto	jmp1
	call	OFF			;Speaker off power save
	decfsz	count6,f	;delay between beeps
	goto	$-1
	decfsz	count7,f	;delay between beeps
	goto	$-3
	decfsz	count5,f	;3 beeps counter
	goto	jmp1
	return

;********************************************************************************

						;Mainprogram
main
	btfsc	test		;check if testinput is high
	call	Test
	call	ANALOG		;read analog input
	call	delay		;delay for sidetone pitch

	decfsz	count1,f	;Timer 10 min for sleep
	goto    main
	decfsz	count2,f
	goto	main
	decfsz	count3,f
	goto	main		;loop back to main... not timed out
;***********************************************************************************

sleeping			
						;going to sleep.. prepare
	call	beeps1

	btfsc	test		;wait for testbutton off
	goto	$-1

	clrf	GPIO		;Before sleep clear everything
	clrf	CCPR1L		;PWM off
	call	delay		;little delay
	
	bsf		INTCON,GPIE	;Enable GPIO interrupt change
	bcf		INTCON,GPIF	;clear GPIO flag bit interrupt
	call	delay
	nop
	nop
	sleep				;goto sleep funktion
	nop
	nop
						;go further to init after sleep
;********************************************************************

							;Init of PIC
			
init    
	BANKSEL OSCCON          ;Switch to Bank 1.
    movlw   b'01100001'     ;4MHz Clk, IntOsc, SysClk via IntOsc
    movwf   OSCCON
	BANKSEL	GPIO	     	;banka tebaks till registersida 0
	clrf	GPIO			;rensa portutgångarna
   
	movlw	b'00000111'		;move 00000111 =digitala i I/O på pinnarna komparatoringångarna
	movwf	CMCON0			;placeras i CMCON0 registret
	movlw   b'00000001'  	;vänsterjustera analogvärdet i de två 8-bitarsregistren, AD=on
	movwf   ADCON0    		;placera i ADCON0 1Fh
	BANKSEL	ANSEL	     	;bank 1
	movlw	b'01101000'		;aktivera AD-modulen och välj klockhastighet i AD-omvandlingen
	movwf	ANSEL			;placera i ANSEL
	movlw	b'00011000'		;välj vilka pinnar som skall vara IN=1, START, STOPP och AD-ingång
	movwf   TRISIO      	;Placera i TRISIO registret
	movlw	b'00000000'		;välj vilka ingångar som skall ha weak pullup
	movwf	WPU				;placera i WPU. Tyvärr har inte GPIO,3 weak pullup...
	movlw	b'00000000'		;aktivate weakpullup bit 7=0
	movwf	OPTION_REG		;placera i OPTION_REG registret
	BANKSEL	IOC
	movlw	b'00011000'		;interrupt on pin GPIO,3
	movwf	IOC

   	BANKSEL GPIO            ;Switch to Bank 0.
							;Set CCP1 as PWM
    movlw   B'00001101'
    movwf   CCP1CON         ;Set bits 4-5 (2 LSB's of Duty Cycle) to 00.
							;Set highest PWM value (resolution),
							;10-bit but only 256 discrete Duty Cycles.
    BANKSEL PR2             ;Bank 1
    movlw   d'255'          ;10-bit res. but 256 Duty Cycles (Duty Cycle LSB = 00)
    movwf   PR2             ;Establishes Timer2 Period.
;
							;Set prescaler to 16 for a PWM freq. of 244Hz (based on 4MHz clock).
							;Since the human eye cannot perceive flicker above 120Hz, 244Hz is OK.
    BANKSEL T2CON           ;Bank 0
    movlw   B'00000001'
    movwf   T2CON           ;Timer2 is now OFF & Prescaler is 16.
       
    clrf    CCPR1L          ;Clear PWM Reg.1 LO Byte (sets PWM Duty Cycle to zero)
;                           ;(CCPR1L contains the 8 MSB's of the Duty Cycle.)
    bsf     T2CON, TMR2ON   ;Turn on Timer2.

	clrf	GPIO			;clearing all pins
	bcf		CCP1CON,4		;clearing low PWM
	bcf		CCP1CON,5
	bsf		ADCON0,3		;read analog input 3  pin GPIO,4
	bsf		ADCON0,2
							;"
	clrf	count1
	clrf	count2
	clrf	count3
	clrf	count4
	clrf	count5
	clrf	count6
	clrf	count7
	bsf		LED
	goto    main   			;to mainprogram
	
	end						;program end