        list            p=16f88

#include "p16f88.inc"

	__CONFIG    _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_ON & _BODEN_OFF & _MCLR_OFF & _PWRTE_OFF & _WDT_OFF & _INTRC_IO

;Program Configuration Register 2
	__CONFIG    _CONFIG2, _IESO_OFF & _FCMEN_OFF

; Chirp number
chirpnum equ 0x26

; Local variables
period equ 0x20
counter equ 0x21
counter2 equ 0x22

startPeriod equ 0x23
chirpSlope equ 0x24
slopeFract equ 0x25
minPeriod equ 0x28
temp equ 0x29	

tonePeriod equ 0x23
toneLength equ 0x24		
			
keylockout equ 0x27
			
        org             0x000
	
	banksel		PORTA
	clrf		PORTA
	
	banksel		ANSEL  	;  Configure PORTA as digital input
	movlw		0x00
	movwf		ANSEL
	movlw		0xff
	movwf		TRISA
	
	banksel		TRISB   ;  Configure PORTB as digital output
        movlw           0x00
	movwf		TRISB

	banksel		OSCCON 	;  Crank up the clock frequency to 125 kHz
	movlw		0x10
	movwf		OSCCON

	banksel		PORTA

        movlw           0x01   ; Initialize waveform selector
        movwf           chirpnum

	bcf		PORTB,4 ;  LED off
	bsf		PORTB,5 ;  Handshake deassert

start   bcf		PORTB,6
	
	btfss           PORTA,0
        call		incnum
	btfss		PORTA,1
	goto		coded_tone1
        goto            start

incnum	incf		chirpnum,f
	bsf		PORTB,4
	call		nullp
	call		nullp
	call		nullp
	bcf		PORTB,4
	call		nullp
	call		nullp
	call		nullp
	bsf		PORTB,4
	call		nullp
	call		nullp
	call		nullp
	bcf		PORTB,4
	return

coded_tone1
	bsf		PORTB,4 ; LED on
	movlw		0x01
	movwf		keylockout
coded_tone2
        movf            chirpnum,w
	andlw		0x07
	movwf		slopeFract
	rlf		slopeFract,f
	incf		slopeFract,f
	
	movlw		0x01
	movwf		chirpSlope
	
	movlw		0x10
	movwf		startPeriod

	movlw		0x01
	movwf		minPeriod
	
	call		chirp
	
	decfsz		keylockout,f
	goto		coded_tone2
	incf		keylockout,f

	call		emit_hs
	goto		start

;;; Generate a pause
nullp	movlw		0xff
	movwf		counter
pauloop decfsz		counter,f
	goto pauloop
	return

;;; Generate a tone
;;; Input:	 tonePeriod = half-period of tone
;;;              toneLength = number of periods to use
tone	movf		toneLength,w
	movwf		counter2

ttop	movf		tonePeriod,w
	movwf		counter
	
	bsf		PORTB,6
tl1	decfsz		counter,f
	goto		tl1
	bcf		PORTB,6
	movf		tonePeriod,w
	movwf		counter
tl2	decfsz		counter,f
	goto		tl2

	decfsz		counter2,f
	goto		ttop
	return

;;; Propagate handshake signal
emit_hs	movlw		0x02
	movwf		counter2
stdly_s	call		nullp
	decfsz		counter2,f
	goto		stdly_s

	bcf		PORTB,5 ; Assert handshake
 	movlw		0x04
	movwf		counter2
stdly_h	call		nullp
	decfsz		counter2,f
	goto		stdly_h
	bsf		PORTB,5 ; Deassert handshake
	bcf		PORTB,4 ; LED off
	return
			
;;; Generate chirp.
;;; Input: startPeriod = initial half-period of the chirp
;;;	   slopeFract  = How often to decrement half-period
;;;        chirpSlope  = how much to decrement half-period
;;;        minPeriod   = smallest allowable period
;;; Returns after one chirpped pulse transmitted
chirp   movf		startPeriod,w
	movwf		period

newper	movf		slopeFract,w
	movwf		counter2
			
edge	bsf		PORTB,6
	movf		period,W
	movwf		counter		
pause	decfsz		counter,f
	goto		pause
	bcf		PORTB,6

	movf		period,W
	movwf		counter		
pause2	decfsz		counter,f
	goto		pause2

	decfsz		counter2,f
	goto		edge

	movf		chirpSlope,w
	subwf		period,f

	movf		period,w
	movwf		temp

	movf		minPeriod,w
	subwf		temp,f
	
	btfss		temp,7
	goto		newper
	
	return
        end
