;Copyright 2004 Richard Cappels, projects@cappels.org ;Program Name: VLFCW -Make 181.818181818181...kHz from 4 Mhz crystal ;vlfcw040711B Changed some macros to subroutines. ;Reload and prescale values .equ XmtTimerReload = $BC ;Timer 0 reload value for T .equ RcvTimerReload = $EF ;Timer 0 reload value for T/4 .equ RecThresh = 40 ;Minimum number of counts to detect carrier. .equ Timer0Prescale = $03 ;Timer 0 prescaler selector .equ delaytime = 20 ;Waiting time after transmit mode before receiving. ;Four callable routines are available. One register isnot saved, RFByte, which is ;used to transfer the data between the RF routines and calling routines and is ;to be a high register (r16-r31). It needs to be delcared as such in program calling this file.. ;Calling other routines may result in modification of other registers. ; ;SendRFByte (subroutine) ;Sends contents of RFChar via RF. Modifies RFChar. ; ;ReceiveRFByte (subroutine) ;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. ; ;PostXmitDelay ;(macro) ;Wait for antenna to stop ringing from xmit. ;Use this delay after transmitting if listening is to follow. The delay allows ;ringing in the antenna to die down so that the ringing is not misatken as data. ;PostRCVDelay ;(macro) ;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 to recover. ; ; ; ; ; ; ; ; ; ; ; ;Reference circuit: ;AT90S2313 microcontroller with 4 MHz clock. ;A resonant loop antennat tuned to 182 kHz is connected across the comparitor intputs, PORTB,0 ; and PORTB,0. ;One such resonant circuit is 14 turns of #30 wire on 5.5 cm in diameter, air core, brought into ;resonance with a .033 uf capacitor in parallel with it. ;BPORTB,1 is also connected to the tap on a 2:1 resistive voltage devider. Both resistors in the ;devider are of the same vlaue and may range from about 220 Ohms to 1 k Ohms each. ;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. ;PORTB,3 is intended to drive an activity indicator LED. It goes high briefly while transmitting ;and receiving data over the RF link. ;*************Code for calling file found below .exit command, below***************** ;//////////////BEGIN BASIC RF COUPLER ROUTINES\\\\\\\\\\\\\\\ .macro pushall push r2 ; push r18 ; push r17 ; push r19; .endmacro .macro popall 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: ldi r18,delaytime rcall delay ret PostRCVDelay: ldi r18, 2 * delaytime rcall delay ret delay: ;Delay - load 00 into r18 for max delay, 01 for minimum delay. ;r18 and r17 destroyed. lptrf1: clr r17 lptrf12: dec r17 brne lptrf12 dec r18 brne lptrf1 ret ReceiveRFByte: ;Receive a byte by RF and put into RFChar ;Returs 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 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 zeinrf1 oirf1: sec zeinrf1: ror RFChar ;Get carry into lsb of RFChar. dec r17 brne nbrf1 sec ;Data received - set carry flag rcxtrf1: ldi r18,0 out TCCR0,r18 ;Turn off timer0 interrupt out ACSR,r18 ;Turn off Comparitor interrupt cbi LEDOutPort,LEDOutPin popall ret bailrf1:clc ;No data received - clear carry and return rjmp rcxtrf1 SendRFByte: ;Shift byte in RFChar out through RF channel. ;RFChar changed by routine. pushall ;Save all working registers except RFChar. sbi LEDOutPort,LEDOutPin ;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 iwzrf1 bitsonerf1: 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 was cleared by shifting.) cbi RFSigPort,RFSigPin ;Set signal output low (no pullup). cbi LEDOutPort,LEDOutPin popall ;Restore all working registes except RFChar. ret szerorf1: ;Send no carrier for for one bit time. ldi r18, XmtTimerReload ;Initialize counter out TCNT0,r18 WaitNotSend: rjmp WaitNotSend ;Do nothing but wait for interrupt to yank out of loop. SendOnerf1: ;Send carrier for T us ldi r18, XmtTimerReload ;Initialize counter out TCNT0,r18 ;Send carrier until next interruput MakeRF1: ;Make 181.8181 Mhz sbi RFSigPort,RFSigPin ;Output High sbi and cbi are 2 clock instructions. 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 rjmp MakeRF1 ;Interrupt will yank out of loop. QCDrf1: ;Send no carrier for T/3 us ldi r18, RcvTimerReload ;Initialize counter out TCNT0,r18 WaitHere1: rjmp WaitHere1 ;Send no carrier until next interruput timer0service: ;Return to routine that called interrupted routine. The processor ;must be in a subroutine when this interrupt occurs! Disable ;the timer the rest of the time. pop r18 pop r18 reti ;Return from interrupt.to routine before interrupt 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 ;******************** Below is code for the calling file *****************************. ;Inlcude the code below in the calling file. It may be customized. Copy the code from here ;to ".exit" into the calling document. ;Copyright 2004 Richard Cappels, projects@cappels.org ;Program Name: VLFCW -Make 181.818181818181...kHz from 4 Mhz crystal ;////////////////// START OF INITIALIZATION CODE \\\\\\\\\\\\\\\\\\\\\\\\\ .include "2313def.inc" ;Include file in same directory as project. .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 bridging resistors .equ BridgePowerDDR = DDRB .equ BridgePowerPin = 2 .def temp = r18 ;General purpose scratch register. .def RFChar = r16 ;RF character I/O buffer ;definition of I/O ;B0 + comparitor input - Antenna Signal ;B1 - comparitor input - Antenna reference ;B2 Bridge power ;B3 LED (high to turn LED on) . ;B4 Receive/Xmit application (for test purposes) ;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 Reserved FOR UART RECEIVE - input has weak pullup ;D1 Reserved FOR UART TRANSMIT - output. ;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 ;Initializaton code rjmp start .ORG $0006 rjmp timer0service ;Timer/counter compare interrupt .ORG $000A rjmp comparitorservice ;Service comparitor interupt .include "vflcw2313.inc" ;Load VLFCW routines ;Four callable routines are available. One register isnot saved, RFByte, which is ;used to transfer the data between the RF routines and calling routines and is ;to be a high register (r16-r31). It needs to be delcared as such in program calling this file.. ;Calling other routines may result in modification of other registers. ; ;SendRFByte (subroutine) ;Sends contents of RFChar via RF. Modifies RFChar. ; ;ReceiveRFByte (subroutine) ;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. ; ;PostXmitDelay ;(macro) ;Wait for antenna to stop ringing from xmit. ;Use this delay after transmitting if listening is to follow. The delay allows ;ringing in the antenna to die down so that the ringing is not misatken as data. ;PostRCVDelay ;(macro) ;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 to recover. ; start: ldi r16,RAMEND ;Initialize Stack Pointer. out spl,r16 ;Set PORTD. ldi temp,0b00000010 out DDRD,temp ldi temp,0b10111111 out PORTD,temp ;Set PORTB. ldi temp,0b00000000 out DDRB,temp ldi temp,0b11110100 out PORTB,temp sbi BridgePowerDDR,BridgePowerPin ;Turn on bridge power sbi LEDOutDDR,LEDOutPin ;Make LED so an output pin. sei ;ENABLE THE INTERRUPTS ;////////////////// END OF INITIALIZATION CODE \\\\\\\\\\\\\\\\\\\\\\\\\ .exit