;RF.S

;Originated from:
;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.

;Modified by:
;Xiaofeng Gu (xg46@cornell.edu), Jia Yang (jy363@cornell.edu)
;For final project of ECE 4760, Spring 2012, Cornell University

 

;*************** 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 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
;vlfcw initialization code.

;.include "m8def.inc" ;Include file in same directory as project.

;How to connect this chip:
;Pin 7 to + 5 V
;Pins 8 and 22 to ground.
;Pin 21 connected to +5V through a decoupling network. For example a 33 uh choke \
; from +5V to pin 21 and a 0.22 uf monolithinc capacitor from pin 21 to ground.
;Pin 6 connects to one end of a 22 uh loop antenna in parallel with a .033 uf capacitor.
;Pin 7 the other end of the loop antenna and capcaitor connect to pin 7, Pin 7 is also
; connected to the center tap of a pair of 220 t 1,000 Ohm resistors connected in series
; between +5V to ground.
;
;The four A/D inputs have an input range of 0 to 5 Volts.
;Pin 23 Analog input A
;Pin 24 Analog input B
;Pin 25 Analog input C
;Pin 26 Analog input D
;
;The output is on-off keyed 182.818181 kHz RF, keyed by serial ASCII
;(1200 baud, 1 start bit, 2 stop bits, no parity, lsb first)
;

;.include "m8def.inc" ;Include file in same directory as project.

;definition of I/O
;B0 (not assigned - configure as INPUT with weak pullup)
;B1 (not assigned - configure as INPUT with weak pullup)
;B2 (not assigned - configure as INPUT with weak pullup)
;B3 (not assigned - configure as INPUT with weak pullup)
;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)
#define __SFR_OFFSET 0
#include <avr/io.h>

;The statements below establish I/O pins needed for RF operation.
.equ RFSigPort , PORTD ;Port output signal is to appear on.
.equ RFSigDDR , DDRD ;Data Direction Register for signal output
.equ RFSigPin , 7 ;Pin output signal is to appear on.

.equ LEDOutPort , PORTD ;Port LED signal is to appear on
.equ LEDOutDDR , DDRD ;Data Direction Register for LED signal
.equ LEDOutPin , 4 ;Pin LED signal is to appear on

.equ RFChar, r20 ;RF character I/O buffer (must be a high register)
.equ temp, r17 ;General purpose scratch register.

;Reload and prescale values

.equ XmtTimerReload, 0x30 ;Timer 0 reload value for T 1 1200 baud value
.equ RcvTimerReload, 0xCC ;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, 0x03 ;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 ;Comparitor interrupt counters
push r18 ;General purpose scratch register
push r17 ;General purpose scratch register.
push r19 ;Temporaty storage of status register

.endm


.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

.endm

.global PostXmitDelay
PostXmitDelay:
push r18 ;Save the r18 register
push r17 ;Save the r17 register
ldi r18,delaytime ;load constant into r18
;to be used in delay subroutine
rcall delay ;call the delay subrouitne for delay
ldi r18,delaytime
rcall delay
ldi r18,delaytime
rcall delay
ldi r18,delaytime
rcall delay
pop r17 ;restore r17 register
pop r18 ;restore r18 register
ret

.global PostRCVDelay
PostRCVDelay:
push r18 ;Save the r18 register
push r17 ;Save the r17 register
ldi r18, rcvmultiplier * delaytime ;load constant into r18
rcall delay ;call subroutine for delay
ldi r18, rcvmultiplier * delaytime
rcall delay
ldi r18, rcvmultiplier * delaytime
rcall delay
ldi r18, rcvmultiplier * delaytime
rcall delay
pop r17 ;restore r17
pop r18 ;restore r18
ret



delay: ;Delay - load 00 into r18 for max delay, 01 for minimum delay.
;r18 and r17 destroyed.
lptrf1: clr r17 ;set r17=0
lptrf12:dec r17 ;r17--
brne lptrf12 ;goto lptrf12 if r17!=0
dec r18 ;r18--
brne lptrf1 ;goto lptrf1 if r18!=0
ret

.global ReceiveRFByte
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 TCCR0B, r18
ldi r18, RcvTimerReload ;Initialize counter.
out TCNT0,r18
lds r18,TIMSK0 ;Enable interrupts TIMSK.
ori r18,0b00000001
sts TIMSK0,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 ;set the rising edge counter to 0
rcall QCDrf1 ;Sample for 1/4 bit time <== use this sample


mov r18,r2 ;copy number of rising edge to r18
cpi r18,RecThresh ;Set carry true if threshold exceeded.
brpl oirf1
clc
rjmp zeinrf1
oirf1: sec
zeinrf1: ror r20 ;Get carry into lsb of RFChar.

dec r17
brne nbrf1 ;check if 8 bits are received

sec ;Data received - set carry flag
ldi r25, 1 ;set r25=1 to indicate data received
mov r24, r20 ;copy the data received into r24 for return
rcxtrf1:
ldi r18,0
out TCCR0B,r18 ;Turn off timer0 interrupt
out ACSR,r18 ;Turn off Comparitor interrupt
cbi LEDOutPort,LEDOutPin
popall ;restore all registers
ret
bailrf1:clc ;No data received - clear carry and return
ldi r25, 0 ;;set r25=0 to indicate no data received
rjmp rcxtrf1

.global SendRFByte
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
mov r20, r24 ;load the pass-in data into the RFChar
ldi r18,Timer0Prescale ;Initaize prescaler
out TCCR0B, r18
ldi r18, XmtTimerReload ;Initialize counter
out TCNT0,r18
lds r18,TIMSK0 ;Enable interrupts TIMSK.
ori r18,1
sts TIMSK0,r18

ldi r17,11 ;Set number of bits:1 start, 8 data, 2 stop
sec ;Prepare to send Start bit
nxbtrf1:
brcs bitsonerf1 ;if is to send one, call bitsonerf1 routine
rcall szerorf1 ;if is to send zero, call szerorf1 routine
rjmp iwzrf1
bitsonerf1:
sbi RFSigDDR,RFSigPin ;Set signal output pin to output.
rcall SendOnerf1 ;Send a bit 1
cbi RFSigDDR,RFSigPin ;Set signal output pin to input.
iwzrf1:
lsr r20 ;Shift next bit into carry.
dec r17 ;Decrement bit counter.
brne nxbtrf1 ;If not all done, then continue.
out TCCR0B,r20 ;(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.181 MHz carrier signal by toggling the PIND.6
sbi RFSigPort,RFSigPin ;Output High sbi and cbi are 2 clock instructions.
sbi RFSigPort,RFSigPin
sbi RFSigPort,RFSigPin
sbi RFSigPort,RFSigPin
sbi RFSigPort,RFSigPin ;5
sbi RFSigPort,RFSigPin
sbi RFSigPort,RFSigPin
sbi RFSigPort,RFSigPin
sbi RFSigPort,RFSigPin
sbi RFSigPort,RFSigPin ;10
sbi RFSigPort,RFSigPin
sbi RFSigPort,RFSigPin
sbi RFSigPort,RFSigPin
sbi RFSigPort,RFSigPin
sbi RFSigPort,RFSigPin ;15
sbi RFSigPort,RFSigPin
sbi RFSigPort,RFSigPin
sbi RFSigPort,RFSigPin
sbi RFSigPort,RFSigPin
sbi RFSigPort,RFSigPin ;20
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
cbi RFSigPort,RFSigPin ;5
cbi RFSigPort,RFSigPin
cbi RFSigPort,RFSigPin
cbi RFSigPort,RFSigPin
cbi RFSigPort,RFSigPin
cbi RFSigPort,RFSigPin ;10
cbi RFSigPort,RFSigPin
cbi RFSigPort,RFSigPin
cbi RFSigPort,RFSigPin
cbi RFSigPort,RFSigPin
cbi RFSigPort,RFSigPin ;15
cbi RFSigPort,RFSigPin
cbi RFSigPort,RFSigPin
cbi RFSigPort,RFSigPin
cbi RFSigPort,RFSigPin
cbi RFSigPort,RFSigPin ;20
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


;//////////////END BASIC RF COUPLER ROUTINES\\\\\\\\\\\\\\\


;.exit