;File name: vlfcwm8.inc
;Copyright 2004 Richard Cappels, projects@cappels.org www.project.cappels.org
;Instructions for use and initialization code are afer the firs .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 -clock/64.
.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 ;
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:
push r18
push r17
ldi r18,delaytime
rcall delay
pop r17
pop r18
ret
PostRCVDelay:
push r18
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.
;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
in r18,TIMSK ;Enable interrupts TIMSK.
ori r18,0b00000001
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 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 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
in r18,TIMSK ;Enable interrupts TIMSK.
ori r18,1
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/4 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
;*************** Following are instructions for use and starter code for the calling .inc file***************
;Inlcude the code below in the calling file. It may be customized.
;Copy the code from "START OF INITIALIZATION CODE" TO "END OF INITIALIZATION CODE",
;below into the assembler source document, then modify as needed.
;REFERENCE CIRCUIT:
;AT<ega8 microcontroller with 4 MHz clock. Timer 0 (8 bit) and the comparitor interrupt are used.
;if this code moved to another controller, the 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.
;The comparitor is used to receive data, The bit configured as the RFSigPort (Port D, pin 6,
;the + input of the comparitor inputs) is used 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.
;The - (non-inverting) input of the comparitor 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 The constants realted to BridgePowerPort designate this pin.
;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.
;The LEDOutPort pin 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 the 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 routine