;**********************************************************************
; cablefinder.asm
; Cablefinder - sender
; Version 0.1
;
; generates alternating sound of ca. 1300 and 650 Hz to inject into end of cable
; purpose is to find the cable with the aid of a corresponding receiver
;
; Usage of Pins:
; GP2 / Pin 5: Output
; GP4 / Pin 3: LED
;
; Assuming INTOSC f=4MHz
;-------------------------------
;Stephan Asmus, Germany
;(c) info@sasmus.de
;
;-------------------------------
; 21.01.2024	Initial Version
;**********************************************************************
	LIST   P=PIC12F675

	#include <p12f675.inc>	; processor specific variable definitions

errorlevel  -302			;No bank select warnings

	__CONFIG (_CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _CPD_OFF & _MCLRE_OFF)

;***** VARIABLE DEFINITIONS
w_temp		EQU	0x20	; used for context saving Register "W"
status_temp	EQU	0x21	; used for context saving Register "Status"

	cblock 0x22			;define a series of variables.
		d1				; Register to hold Delayloop	
		tcount			;counts timer0 overflows
		ledcount		;counts cycles for led blinking
        endc

#define output	GPIO,2	;output
#define	led		GPIO,4	;indicator LED

; **********************************************************************
; **********************************************************************
	ORG		0x000			; processor reset vector
	goto	init			; go to beginning of program

	ORG		0x004			; interrupt vector location
	movwf	w_temp			; save off current W register contents
	swapf	STATUS,W		; move status register into W register
	clrf	STATUS			; select Bank 0
	movwf	status_temp		; save off contents of STATUS register
							; There's no need to save PCLATH since
							; i'll stick to Bank 0 of program memory.
	btfsc	INTCON,T0IF		; If Timer 0 caused the interrupt, handle it.
	call	timer0

	swapf	status_temp,w	; retrieve copy of STATUS register
	movwf	STATUS			; restore pre-isr STATUS register contents
	swapf	w_temp,f
	swapf	w_temp,w		; restore pre-isr W register contents
	retfie					; return from interrupt

; ------------------------------------------------------------------------------
;       Timer 0 Interrupt handler.
;       Timer 0 has overflowed
; ------------------------------------------------------------------------------
timer0
	incf	tcount,f
	BCF 	INTCON,T0IF		; Clear Timer0 flag and continue.
	return

; ------------------------------------------------------------------------------
; START OF CODE to initialize the processor (Variables, I/O ...)
; ------------------------------------------------------------------------------
init
	bcf		STATUS,RP0		; Select Bank 0

	movlw 	07h
	movwf 	CMCON			;comparator off
	clrf	GPIO			; Init I/O-Port by clearing the outp. latches.

	bsf		STATUS, RP0		;Switch to BANK 1
	clrf	ANSEL			;All digital I/O
	clrf	IOC				;No Interrupt on change
	clrf 	TRISIO			;all output
	;calibrating the oscillator...
	call	3FFh 			;Get the cal value
	movwf	OSCCAL 			;Calibrate it
	bcf		STATUS, RP0		;Back to BANK 0

; initialize Timer 0
	clrwdt				
	clrf	TMR0	
	;---
	bsf		STATUS, RP0		;Switch to BANK 1
	movlw	b'11010110'		;Prescaler to timer 0, Prescaler to 128
	movwf	OPTION_REG
	bcf		STATUS, RP0		;Back to Bank 0
	clrf	TMR0			;start timer with 0
							;overflow every 32,8ms
	;initialize variables
	clrf	tcount	
	clrf	ledcount
	bcf		led		
	bcf		output

	clrf	INTCON			;initialise Interrupts
	bsf		INTCON,T0IE		;enable Timer0 interrupts
	bsf		INTCON,GIE		;enable global interrupts
							;now timer 0 fires        
; ******************************************************************************
; MAIN, here we go...
; ******************************************************************************
mainloop

do1300
	;first generate 200ms of 1300Hz
	movlw	b'00000100'		;toggle bit 2 of GPIO (output)
	xorwf	GPIO,f
	call	delay385us		;one half of 1300Hz cycle
	movf	tcount,w
	xorlw	0x06			;about 200ms over?
	btfss	STATUS,Z
	goto	do1300			;no, then go on
	
	clrf 	tcount			;start new 200ms cycle

do700
	;then generate 200ms of 650Hz
	movlw	b'00000100'		;toggle bit 2 of GPIO (output)
	xorwf	GPIO,f
	call	delay714us		;one half of 650Hz cycle
	movf	tcount,w
	xorlw	0x06			;about 200ms over?
	btfss	STATUS,Z
	goto	do700			;no, then go on

	clrf 	tcount			;start new 200ms cycle
	incf	ledcount,f		;blink LED
	movlw	0x02
	xorwf	ledcount,w
	btfss	STATUS,Z		; 2*2*200ms over?
	goto	mainloop		;no, leave led
	movlw	b'00010000'		;otherwise toggle LED
	xorwf	GPIO,f
	clrf	ledcount		;start new cycle

	goto mainloop			;and from beginning....

; ------------------------------------------------------------------------------
; delay: several delay routines used in the program
; ------------------------------------------------------------------------------
delay385us
			;385 cycles
	movlw	0x80
	movwf	d1
Delay_0
	decfsz	d1, f
	goto	Delay_0
	return
;----
delay714us
			;712 cycles
	movlw	0xED
	movwf	d1
Delay_1
	decfsz	d1, f
	goto	Delay_1

			;2 cycles
	goto	$+1
	return

; *****************************************************************
	END					;'end of program''
