;File name: vlfcw2313.inc;Copyright 2004 Richard Cappels, projects@cappels.org   www.project.cappels.org;Instructions for use and initialization code are afer the first .exit statement.;Reload and prescale values.equ	XmtTimerReload	= $CC 		;Timer 0 reload value for T 1 1200 baud value.equ	RcvTimerReload	= $F3		;Timer 0 reload value for T/4 1200 baud value.equ	RecThresh	=  10 		;Minimum number of counts to detect carrier..equ	RecHighThres	=  65 		;1+ maximum counts for valid carrier.equ	Timer0Prescale	= $03		;Timer 0 prescaler selector.equ	delaytime	=  20		;Waiting time after transmit mode before receiving..equ	rcvmultiplier 	=   7		;Number of delaytimes to wait bafter receiving before transmitting.;//////////////BEGIN BASIC RF COUPLER ROUTINES\\\\\\\\\\\\\\\		.macro	pushall	push	r2			;Save these registers before using		push	r18			;in the VLF communications routines.	push	r17	push	r19;						.endmacro																						.macro	popall				;Restore these registers before returning.		pop	r19;			;Temporaty storage of status register.	pop	r17			;General purpose scratch register.	pop	r18			;General purpose scratch register.	pop	r2			;Comparitor interrupt counters.										.endmacro																						PostXmitDelay:				;Delay for electrical settling before	push	r18			;switching to receive mode.	push	r17	ldi	r18,delaytime	rcall	delay	pop	r17	pop	r18	ret	PostRCVDelay:				;Delay long enough for receiver on far end	push	r18			;to switch to receive mode, befor transmitting.	push	r17	ldi	r18, rcvmultiplier * delaytime	rcall	delay	pop	r17	pop	r18	ret					delay:					;Delay - load 00 into r18 for max delay,					;01 for minimum delay. Registers r18 and r17 are modified..lptrf1:	clr	r17lptrf12:dec	r17	brne	lptrf12	dec	r18	brne	lptrf1	ret	ReceiveRFByte:				;Receive a byte by RF and put into RFChar					;Returns with carry set if data received, otherwise cleared.	pushall				;Save working registers on stack	ldi 	r18,Timer0Prescale	;Initaize prescaler.	out 	TCCR0, r18	ldi 	r18, RcvTimerReload	;Initialize counter.	out 	TCNT0,r18	ldi 	r18, $02		;Enable interrupts TIMSK.	out 	TIMSK,r18	clr	r2			;Zero comparitor interrupt counter.	ldi	r17,0b00001011		;Comparitor setup: enable interrupt on positive edge.	out	ACSR,r17	clr	r17			;Clear start bit test counter.	wfsbrf1:				;Wait for start bit.	rcall	QCDrf1			;Sample for 1/4 bit time.	dec	r17			;See if too many consecutive unsuccessful samples.	breq	bailrf1	mov	r18,r2	cpi	r18,RecThresh		;Check number of carrier cycles against threshold.	brmi	wfsbrf1	cpi	r18,RecHighThres	;Check to see if too many carry cycles received.	brpl	wfsbrf1											rcall	QCDrf1			;Wait T/4.	rcall	QCDrf1			;Wait T/4.	ldi	r17,8			;Set number of bits: 8 data.nbrf1:	sbi	LEDOutPort,LEDOutPin	rcall	QCDrf1			;Wait T/4.	rcall	QCDrf1			;Wait T/4.	rcall	QCDrf1			;Wait T/4.	clr	r2	rcall	QCDrf1			;Sample for 1/4 bit time <== use this sample	mov	r18,r2	cpi	r18,RecThresh		;Set carry true if threshold exceeded.	brpl	oirf1	clc	rjmp	zeinrf1oirf1:	seczeinrf1:ror	RFChar			;Get carry into lsb of RFChar.	dec	r17	brne	nbrf1	sec				;Character received - set carry flagrcxtrf1:	ldi	r18,0	out	TCCR0,r18		;Turn off timer0 interrupt	out	ACSR,r18		;Turn off Comparitor interrupt		cbi	LEDOutPort,LEDOutPin				popall	retbailrf1:clc				;No data received - clear carry and return		rjmp	rcxtrf1			SendRFByte:				;Shift byte in RFChar out through RF channel.					;RFChar changed by this routine.	pushall				;Save all working registers except RFChar.	sbi	LEDOutPort,LEDOutPin	;Turn on LED for indication purposes.	ldi 	r18,Timer0Prescale	;Initaize prescaler	out 	TCCR0, r18	ldi 	r18, XmtTimerReload	;Initialize counter 	out 	TCNT0,r18	ldi 	r18, $02		;Enable interrupts TIMSK	out 	TIMSK,r18	ldi	r17,11			;Set number of bits:1 start, 8 data, 2 stop	sec				;Start bit					nxbtrf1:	brcs	bitsonerf1		rcall	szerorf1		rjmp	iwzrf1bitsonerf1:	sbi	RFSigDDR,RFSigPin 	;Set signal output pin to output.	rcall	SendOnerf1	cbi	RFSigDDR,RFSigPin 	;Set signal output pin to input.iwzrf1:	lsr	RFChar			;Shift next bit into carry.	dec	r17			;Decrement bit counter.	brne	nxbtrf1			;If not all done, then continue.	out	TCCR0,RFChar		;(RFChar is now cleared because of shifting.)		cbi	RFSigPort,RFSigPin 	;Set signal output low (no pullup).	cbi	LEDOutPort,LEDOutPin	;Turn off the LED.	popall				;Restore all working registes except RFChar.	retszerorf1:				;Send no carrier for for one bit time.	ldi 	r18, XmtTimerReload	;Initialize counter 	out 	TCNT0,r18WaitNotSend:	rjmp	WaitNotSend		;Do nothing but wait for interrupt to yank controller out of loop.SendOnerf1:				;Send carrier until interrupted.	ldi 	r18, XmtTimerReload	;Initialize counter 	out 	TCNT0,r18		;Send 181.818 kHz (4 MHz clock) carrier until next interruputMakeRF1:				;This is a timing loop, so modify carefully!	sbi	RFSigPort,RFSigPin	;Output High. Instructions sbi and cbi are 2 clock each.	sbi	RFSigPort,RFSigPin		sbi	RFSigPort,RFSigPin	sbi	RFSigPort,RFSigPin	sbi	RFSigPort,RFSigPin	nop				;(need this nop for timing)	cbi	RFSigPort,RFSigPin	;Output Low	cbi	RFSigPort,RFSigPin	cbi	RFSigPort,RFSigPin	cbi	RFSigPort,RFSigPin	nop				;(need this nop for timing)	rjmp	MakeRF1			;Interrupt will yank controller out of loop.	QCDrf1:					;Send no carrier for 1/4 bit time.	ldi 	r18, RcvTimerReload	;Initialize counter 	out 	TCNT0,r18WaitHere1:	rjmp	WaitHere1		;Send no carrier until next interruputtimer0service:				;Return to routine that called interrupted routine. The processor 					;must be in a subroutine when this interrupt occurs!  Disable 					;the timer when not in a routine you want to be "interrupted out of"..	pop	r18	pop	r18	reti				;Return from interrupt.to routine that called interrupted subroutine.		comparitorservice:			;Increment r18 upon comparitor interrupt.		in	r19,sreg		;Save status register.	inc	r2			;Increment SigCount.	out	sreg,r19		;Restore status register.	reti				;Return from interrupt. Total of 7 cycles including the return.	;//////////////END BASIC RF COUPLER ROUTINES\\\\\\\\\\\\\\\				.exit;*************** Following are instructions for use and starter code for the calling .inc file***************;Inlcude the code below in the calling file. ;Copy the code from "START OF INITIALIZATION CODE" TO "END OF INITIALIZATION CODE", ;below into the assembler source document.This code can then be modified to fit;the application.	;REFERENCE CIRCUIT:;AT90S2313 microcontroller with 4 MHz clock. Timer 1 (8 bit) and the comparitor interrupt are used.;if this code moved to another controller, the parts of this include file code relating to these ;peripherals will most likely have to be modified.;A resonant loop antennat tuned to 182 kHz is connected across the comparitor intputs, PORTB,0;and PORTB,1.The comparitor is used to receive data, Port B,0 is turned into an output to send;data.;One example resonant circuit is 14 turns of #30 emammeled wire on 5.5 cm in diameter air core, ;brought into resonance with a .033 uf capacitor in parallel with it.;PORTB,1 is also connected to the tap on a 2:1 resistive voltage devider, which serves to bias;the resonant circuit at half the supply voltage. Both resistors in the devider are of the same ;vlaue and may range from about 220 Ohms to 2 k Ohms each. The value of these resistors determines;the maximum possible transmitter power.;The voltage devider may be power from the microcontroller's positive power supply, or optionally,;powered from one of its output pins PORTB,2 has been designated for this purpose. Powering;from an output pin allows power reduction during sleep. The example initialization code sets;this pin high. Additoinal code would be needed to set this pin low for power saving.;PORTB,3 is intended to drive an activity indicator LED. It goes high briefly while transmitting;and receiving data over the RF link. The example initialization code sets this pin as an output.;If this pin is needed for some other function, code that controls the pin will have to be removed;from the initialization and this include file.;CALLABLE SUBROUTINES:;Four callable routines are available. Each of these routines saves all working registers on the ;stack and restores thme before returning to the calling routines. The sole exception is, ;RFChar, which is used to transfer the data between the RF routines and calling routines.;RFchar needs to be assigned to a high register (r16..r31),but CANNOT be r17, r18. or r19.;RFChar is only modified by the RF routines while one of the four callable routines is being executed, and;may be used freely in other parts of the program.;Here is a list of the callable routines:;SendRFByte	(subroutine)	Sends contents of RFChar;Sends contents of RFChar via RF. Modifies RFChar.;Example;	ldi	RFChar,$2A		;Send astersik via RF link.;	rcall	SendRFByte		;;ReceiveRFByte	(subroutine)	Receive 	RF singal into RFChar, carry set if successful.;Waits for start bit on RF channel for 63.75 bit times. Returns with carry set and ;data in RFChar if character received. Returns with carry clear if no byte received within;that time.;Example;getchar:;	rcall	ReceiveRFByte		;Wait for character to be received;	brcc	getchar;	;PostXmitDelay	(subroutine)	;Wait for antenna to stop ringing from transmit operation.;Use this delay after transmitting if listening is to follow. The delay allows;ringing in the antenna to die down so that the received does not mistake ringing as data.;This is meant to be used when between sending mode and receiving modes, not to be ;used on a character-by-character basis, as this would needlessly reduce the data;rate.;See example below "PostRCVDelay".;PostRCVDelay	(subroutine)	;Wait for far end receiver to recover.	;Use this after receiving data, before sending to give the receiver associated;with the transmitter that just sent data time to recover. This is meant to be used;when switching between receiving mode and sending modes, not to be used on a;character-by-character basis, as this might result in the loss of garbling;of characters within a stream.;	;Example				;Receive a character via RF and echo it back via RF.;;wait:	rcall	ReceiveRFByte		;Wait for a character to be received;	brcc	wait		;	rcall	PostRCVDelay		;Wait for rining in far end transmitter to stop.;	rcall	SendRFByte		;Echo character to far end.;	rcall	PostXmitDelay		;Wait for rining in local antenna to die down.;	rjmp	wait			;Go back to top and get another character.;////////////////// START OF INITIALIZATION CODE \\\\\\\\\\\\\\\\\\\\\\\\\;Copyright 2004 Richard Cappels, projects@cappels.org;vlfcw2313 initialization code..include "2313def.inc"		;Include file in same directory as project.;The statements below establish I/O pins needed for operation..equ	RFSigPort	= PORTB	;Port output signal is to appear on..equ	RFSigDDR	= DDRB	;Data Direction Register for signal output.equ	RFSigPin	= 0	;Pin output signal is to appear on..equ	LEDOutPort	= PORTB	;Indicator LED.equ	LEDOutDDR	= DDRB.equ	LEDOutPin	= 3.equ	CompPlusPort	= PORTB	;Comparitor noninverting input (input 0).equ	CompPlusDDR	= DDRB.equ	CompPlusPin	= 0.equ	BridgePowerPort	= PORTB	;Power for voltage devider (bridging resistors).equ	BridgePowerDDR	= DDRB.equ	BridgePowerPin	= 2.def	RFChar		= r16	;RF character I/O buffer (must be a high register);definition of I/O;B0	+ comparitor input - Antenna Signal;B1	- comparitor input - Antenna reference;B2	Devider (bridge power) optional.		;B3	LED (high to turn LED on)	.	;B4	(not assigned - configure as INPUT with weak pullup)	;B5	(not assigned - configure as INPUT with weak pullup)	;B6	(not assigned - configure as INPUT with weak pullup)	;B7	(not assigned - configure as INPUT with weak pullup)	;D0	(not assigned - configure as INPUT with weak pullup);D1	(not assigned - configure as INPUT with weak pullup);D2	(not assigned - configure as INPUT with weak pullup);D3	(not assigned - configure as INPUT with weak pullup);D4	(not assigned - configure as INPUT with weak pullup);D5	(not assigned - configure as INPUT with weak pullup);D6	(not assigned - configure as INPUT with weak pullup);D7	(not assigned - configure as INPUT with weak pullup).cseg	.ORG $0000		rjmp	start			;Initializaton code.ORG $0006 		rjmp	timer0service		;Timer/counter compare interrupt.ORG $000A	rjmp	comparitorservice	;Service comparitor interupt.include "vlfcw2313.inc"		;Load VLFCW routines after last vector assignment					;but before start of application code. This .inc file					;is expected to be in the same directory as this calling					;program.start:   	ldi	r16,RAMEND		;Initialize Stack Pointer. Note; AT90S2313 has 8 bit pointer.	out	spl,r16					;Set PORTD.	ldi	RFChar,0b00000000			out	DDRD,RFChar	ldi	RFChar,0b10111111	out	PORTD,RFChar						;Set PORTB.	ldi	RFChar,0b00000000			out	DDRB,RFChar	ldi	RFChar,0b11110100	out	PORTB,RFChar					sbi	BridgePowerDDR,BridgePowerPin ;Turn on bridge power ;Optional	sbi	LEDOutDDR,LEDOutPin	;Make LED so an output pin.	sei				;ENABLE THE INTERRUPTS			;////////////////// END OF INITIALIZATION CODE \\\\\\\\\\\\\\\\\\\\\\\\\		.exit