Full Version : Minimum Mass Wireless Frequency Meter (AVR ASM)
avr >>PROJECTS (AVR) >>Minimum Mass Wireless Frequency Meter (AVR ASM)


AVR_Admin- 04-28-2006
Minimum Mass Wireless Coupled Frequency Meter by Dick Cappel

A 0 to 2 MHz ferquency meter with a Minimum Mass Wireless Coupler, based on the ATMega8.Range to the Minimum Mass Base Unit is 10 to 15 cm. Since the frequency meter is battery operated, it can be floated from ground, making life in and around the test bench a lot simpler. No need to connect it to the computer or LCD display - just turn in on and place it next to the base unit.

The basic Minimum Mass Wireless Coupler technology is described and links to other projects on this site that use the Minimum Mass Wireless Coupler are located on the web page, Minimum Mass Wireless Coupler.


The all parts except the loop antenna fit inside a battery case.
The loop was squashed a little bit to make it fit the shape of
the case.

The circuit is as simple as it can get and still work.
Wiring is not critical.

A simple one chip frequency meter was the first instrument I updated with the Minimum Mass Wireless Coupler. The frequency meter is self-contained, including batteries. The only external electrical connection is pair of wires to connect to the signal being measured. To use it, I merely attach the input leads to the signal I want to measure, place the meter next to the base unit and switch it on. The activity LEDs blink on both enclosures as the frequency meter sends its command menu and -voila! -the menu prints on my computer screen and the system is ready for taking measurements.

After the frequency meter sends its command menu, it "disconnects" from the RF channel. In other words, it does not respond to commands or send data until it receives an ASCII control-A character, which is its reconnect command. A control-B character from the keyboard disconnects the meter from the channel again. Other devices use different control codes, for example, the scanning voltmeter uses control-C do connect and control-D to disconnect. This discipline allows multiple Minimum Mass Wireless Coupler equipped devices to share the same Base Unit without interfering with each other.

As long as the input signal swings through the chip's logic switching thresholds, it will be counted. As the battery voltage drops lower and lower, the 1N916 protection diodes will keep the input pin on the controller from exceeding the maximum current shown on the data sheet. A further protection is the upside-down transistor connected as a low current zener diode, just in case the batteries a large signal is applied to the input leads when the power is off.

A battery saver shuts down the controller and power to the bias resistors if the circuit does not receive a command for a long period of time. This one feature has saved me from having to replace the batteries a number of times already.

With respect to firmware, this is basically the RS-232 Freq. Meter/Pulse Generator Based on Atmel AT902313 from elsewhere on this site. I just removed the pulse generator part of it and replaced the calls to the UART with calls to the Minimum Mass Wireless Coupler driver, which are provided by the .inc file.

The red "operating" and the green "ready" LEDs from the original design were not used becasue this is a battery powered device, and with that scheme, one LED is to be on all the time the unit is powerd up. As it is, there is one yellow LED that indicates activity on the Minimum Mass Wireless Coupler and that is enough.

Link to Site: http://cappels.org/dproj/minmassrffm/minmassrffmtr.html

CODE

;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 r17
lptrf12: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 zeinrf1
oirf1: sec
zeinrf1:ror RFChar  ;Get carry into lsb of RFChar.
dec r17
brne nbrf1
sec   ;Character 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 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 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 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.
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 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 interruput
MakeRF1:   ;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,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 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



CODE

;Program Name: vlffmtr2313.asm   Frequency meter wtih VLF serial link.
;Copyright 2004 Richard Cappels, projects@cappels.org   www.project.cappels.org


.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



;***** 16 bit binary-to-packed-BDC Subroutine Register Variables

.equ AtBCD0 =13 ;address of tBCD0
.equ AtBCD2 =15 ;address of tBCD1

.def tBCD0 =r13 ;BCD value digits 1 and 0
.def tBCD1 =r14 ;BCD value digits 3 and 2
.def tBCD2 =r15 ;BCD value digit 4

.def fbinL =r16 ;binary value Low byte
.def fbinH =r17 ;binary value High byte
.def cnt16a =r18 ;loop counter
.def tmp16a =r19 ;temporary value

;***** other register assignments


.def  rbglc   =r1
.def presetrbglc  =r2;1,$0A number of seconds when loopmultiplier is = $64
.def presetloopmultiplier =r3; $64, $01 number of 10 ms increments
.def presetdelaycounter =r4; $F4
.def presetdelaycounter1 =r5; $27


.def Idle1   =r6
.def Idle2   =r7
.def idlecompare  =r8
.def flags   =r9

.def inbytehh  =r20;Higher byte for asci-hex conversion
.def temp   = r22;General purpose register
.def  delaycounter  = r23
.def  delaycounter1  = r24
.def  loopmultiplier  = r25
.def RFChar   = r26;RF character I/O buffer
.def inbytel   = r28   ;Lower byte for asci-hex conversion
.def inbyteh   = r19;Data to be sent via wireless port



;Definition of flags register
;0 if set, disable battery timer.
;1
;2
;3
;4
;5
;6
;7


;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 Counter input for frequency meter
;D6 (not assigned - configure as INPUT with weak pullup)
;D7 (not assigned - configure as INPUT with weak pullup)



.cseg

.ORG $0000  
rjmp start
.ORG $0006
rjmp timer0service;Timer/counter compare interrupt -for RF
.ORG $000A
rjmp comparitorservice;Service comparitor interupt -for RF

.include "vlfcw2313.inc";This include file must be loaded here. File is expected to be.
  ;in the same directory as this file.

DisableBatteryTimer:
set
bld flags,0
ldi     ZH,high(2*Batteryoffmessage);Load high part of byte address into ZH
ldi     ZL,low(2*Batteryoffmessage);Load low part of byte address into ZL
rcall  sendstring  ;Send "Battery timer OFF" message.
rjmp loop







Disconnect:
ldi     ZH,high(2*offmessage);Load high part of byte address into ZH
ldi     ZL,low(2*offmessage);Load low part of byte address into ZL
rcall  sendstring ;Send "DISCONNECTED" message.
stiloff:
rcall rs_rec  ;Wait for Control-A
cpi RFChar,$01
brne stiloff
ldi     ZH,high(2*onmessage);Load high part of byte address into ZH
ldi     ZL,low(2*onmessage);Load low part of byte address into ZL
rcall  sendstring ;Send "CONNECTED" message.
rjmp loop

MeasureOnce:  ;Measure frequency one time..
rcall measurefreq
rjmp  loop      

start:    ;Startup routine
ldi r16,RAMEND ;Initialize Stack Pointer (AT90S2313 has an 8 bit stack pointer)..
out spl,r16
clr flags  ;Set all bits in flagreg (flag register) to zero.

ldi temp,0b00000010 ;Set PORTD.
out DDRD,temp
ldi temp,0b11011111
out PORTD,temp
ldi temp,0b00000000 ;Set PORTB.
out DDRB,temp
ldi temp,0b11110100
out PORTB,temp  
   ;The Three statements below are for the VLF RF link.
sbi BridgePowerDDR,BridgePowerPin;Turn on bridge power
sbi LEDOutDDR,LEDOutPin;Make LED so an output pin.
sei   ;Enable interrupts.

rcall TypeGreeting
rcall makeit1s ;Set default measurement time to 1 second and jump to loop
rjmp Disconnect
loop:    ;*****command interpretation loop****
ldi RFChar,$3A ;Send prompt (colon char) to terminal
rcall SendRFByte
ldi RFChar,$20
rcall SendRFByte
ldi RFChar,$20
rcall SendRFByte
rcall rs_rec  ;Get char from host and interpret char


cpi RFChar,$3F ;If ? then display the menu.
breq domenu
cpi RFChar,$21 ;If ! then use watchdog timer to reset the chip.
breq pull_the_plug
andi RFChar,$DF ;Make upper-case ascii

cpi RFChar,'T' ;If it is a T then disable the battery timer.
breq DisableBatteryTimer;(Resetting the chip resets this flag).
 

cpi RFChar,$52 ;If R or r, measure frequency over and over.
breq MeasureRepetitive
cpi RFChar,$0D ;If Retrun measure frequency
breq MeasureOnce
cpi RFChar,$41 ;A 10ms
breq set10ms
cpi RFChar,$42 ;B 100ms
breq set100ms
cpi RFChar,$43 ;C 1s
breq  set1s
cpi RFChar,$44 ;D 10s
breq  set10s
cpi RFChar,$45 ;E 100s
breq  goto100secondrealy
cpi RFChar,$02 ;Control-B -idle until Control-A received.
breq Disconnect
rjmp loop  ;Go get another char to interpret.



MeasureRepetitive:  ; Measure frequency over and over again until RF detected.
ldi     ZH,high(2*Repetitivemessage);Load high part of byte address into ZH
ldi     ZL,low(2*Repetitivemessage);Load low part of byte address into ZL
rcall  sendstring  ;Send "Repetitive measurement" message.
rcall ClearIdleTimeShort ;Preset idle timer (battery saver).
MeasureAgain:
rcall IdleTime  ;Increment idle timer and sleep if its time.
rcall measurefreq  ;Measure the frequency at the input.
rcall ReceiveRFByte  ;See is present to interrupt the measuremnets.
brcc MeasureAgain  ;If no RF, continute taking measurements.
rjmp  loop        
   
domenu:
rcall TypeGreeting  ;Type the user menu.
rjmp  loop   ;Go back to main loop.


pull_the_plug:    ;Reset the controller using the watchdog timer.
ldi     ZH,high(2*resetmessage)     ;Load high part of reset message address into ZH.
ldi     ZL,low(2*resetmessage)     ;Load low part of reset message address into ZL.
rcall  sendstring  ;Send reset message via RF.
wdr    ;Reset then enable watchdog timer and wait for hardware reset
ldi temp,$08
out wdtcr,temp
wait_for_reset:    
rjmp wait_for_reset  ;Loop until watchdog resets the controller.

   
goto100secondrealy: rjmp set100s ;Here because of size of relative branch in AT90S2313.

set10ms:    ;Set registers for a 10 millisecond measuremnet and send notice.
ldi temp,$01
mov presetrbglc,temp
ldi temp,$01
mov presetloopmultiplier,temp  
ldi temp,$F4
mov presetdelaycounter,temp
ldi temp,$27
mov presetdelaycounter1,temp    
     ldi     ZH,high(2*tenmsmessage) ;Load high part of byte address into ZH
     ldi     ZL,low(2*tenmsmessage) ;Load low part of byte address into ZL
     rcall   sendstring
rjmp loop


set100ms:    ;Set registers for a 100 millisecond measuremnet and send notice.
ldi temp,$01
mov presetrbglc,temp
ldi temp,$0A
mov presetloopmultiplier,temp  
ldi temp,$F4
mov presetdelaycounter,temp
ldi temp,$27
mov presetdelaycounter1,temp    
     ldi     ZH,high(2*hundredmsmessage);Load high part of byte address into ZH
     ldi     ZL,low(2*hundredmsmessage);Load low part of byte address into ZL
     rcall     sendstring
rjmp loop

   
set1s:     ;Set registers for a 1 second measuremnet and send notice.
rcall makeit1s
rjmp loop
   
   
makeit1s:
    ldi temp,$01
mov presetrbglc,temp
ldi temp,$64
mov presetloopmultiplier,temp  
ldi temp,$F4
mov presetdelaycounter,temp
ldi temp,$27
mov presetdelaycounter1,temp    
     ldi     ZH,high(2*onesmessage) ;Load high part of byte address into ZH
     ldi     ZL,low(2*onesmessage) ;Load low part of byte address into ZL
     rcall     sendstring
ret
   
set10s:     ;Set registers for a 100 second measuremnet and send notice.
ldi temp,$0A
mov presetrbglc,temp
ldi temp,$64
mov presetloopmultiplier,temp  
ldi temp,$F4
mov presetdelaycounter,temp
ldi temp,$27
mov presetdelaycounter1,temp    
     ldi     ZH,high(2*tensmessage) ;Load high part of byte address into ZH
     ldi     ZL,low(2*tensmessage) ;Load low part of byte address into ZL
     rcall     sendstring
rjmp loop
   
set100s:    ;Set registers for a 100 second measuremnet and send notice.
ldi temp,$64
mov presetrbglc,temp
ldi temp,$64
mov presetloopmultiplier,temp  
ldi temp,$F4
mov presetdelaycounter,temp
ldi temp,$27
mov presetdelaycounter1,temp    
     ldi     ZH,high(2*hundredsmessage);Load high part of byte address into ZH
     ldi     ZL,low(2*hundredsmessage);Load low part of byte address into ZL
     rcall     sendstring
rjmp loop

   
rs_rec:    
rcall ClearIdleTime  ;Keep track of time no input from terminal received
rec_more:    ;for the purposes of the battery saver.
rcall IdleTime
rcall ReceiveRFByte  ;Wait for carry to come back high.
brcc rec_more  
  rcall PostRCVDelay  ;Wait for far end to be ready to receive before leaving.
   ret
   
 



crlf:     ;Send carriage return and line feed (the hard way).
ldi ZH,high(2*crlfmessage) ;Load high part of byte address into ZH
ldi ZL,low(2*crlfmessage) ;Load low part of byte address into ZL
rcall sendstring
ret



sendstring:    ;Send Flash string. Call with location of string in Z.
lpm    ;Load byte from program memory into r0
tst r0   ;Check if we've reached the end of the message
breq finishsendstering ;If so, return
mov  RFChar,r0
rcall SendRFByte
adiw ZL,1   ;Increment Z registers
rjmp sendstring  ;If not the end, the keep sending until $00 is encountered.
finishsendstering:
ret



sendline:    ;Send a string followed by a cariage return and line feed.
    ;Call with location of start of string in Z.            
     rcall     sendstring
     rcall     crlf
     ret


TypeGreeting:    ;Send power on/reset message via RF link.
rcall crlf
rcall crlf
ldi ZH,high(2*hellomessage) ;Load high part of byte address into ZH
ldi ZL,low(2*hellomessage) ;Load low part of byte address into ZL
rcall sendline  ;Sent it.
ret


byte_to_asciihex:   ;Convert byte in inbytel to ascii in inbyteh,inbytel.
mov inbyteh,inbytel
lsr inbyteh   ;Convert the high nybble to ascii byte
lsr inbyteh
lsr inbyteh
lsr inbyteh
subi inbyteh,$D0      ;Add $30.
cpi inbyteh,$3A    
brlo PC+2            ;If less than 9 skip next instruction.
subi inbyteh,$F9      ;Add 8 to ASCII (if data greater than 9).
    ;(Byte in inbyteh represents upper nybble that was in
    ;inbytel at start)
andi inbytel,0b00001111 ;Convert the lower nybble to ascii byte.
subi inbytel,$D0      ;Add $30.
cpi inbytel,$3A    
brlo PC+2            ;If less than 9 skip next instruction.
subi inbytel,$F9      ;Add 8 to ASCII (if data greater than 9).
ret


sendbyte:          ;Send byte contained in inbytel to terminal.
rcall byte_to_asciihex
mov RFChar,inbyteh
rcall SendRFByte
mov RFChar,inbytel
rcall SendRFByte
ret





;******************* MEASURE FREQUENCY


measurefreq:
ldi temp,$00  ;Set tccr1a (contorl of 16 bit counter) to all zeros
out tccr1a,temp
ldi temp,$00  ;Clear 16 bit counter
out tcnt1h,temp
out tcnt1l,temp
ldi temp,$06  ;Enable input to counter 1
out tccr1b,temp
mov rbglc,presetrbglc
reallybigloop:
       
mov loopmultiplier,presetloopmultiplier;****10 ms = $01, 100 ms =  $0A, 1 second = $64
bigloop:
mov  delaycounter,presetdelaycounter ;Set values for delay of 10 ms. delaycounter = $F4, delaycounter1 = $27
mov  delaycounter1,presetdelaycounter1  
 
dealylooproutine:    ;10 millisecond dealy loop.

dec delaycounter
cpi delaycounter,$00
brne dealylooproutine
dec delaycounter1
cpi delaycounter1,$00
brne dealylooproutine  
nop    ;A little extra delay.
nop
nop
dec  loopmultiplier
brne bigloop
dec rbglc
brne reallybigloop

ldi temp,$00  ;Stop 16 bit counter.
out tccr1b,temp
    ;Display the data.
in fbinL,tcnt1l  ;Move counter contents to input for number conversion.
in fbinH,tcnt1h
rcall bin2BCD16  ;Convert to 2.5-byte packed BCD format.
rcall  crlf  
mov RFChar,tBCD2
ldi temp,$30
add RFChar,temp
rcall  SendRFByte
mov inbytel,tBCD1
rcall sendbyte
mov inbytel,tBCD0  ;Since leading digit on high byte is always zero, dont' sent it.
rcall sendbyte
ldi RFChar,$20
rcall SendRFByte
ret

;**** A P P L I C A T I O N   N O T E   A V R 2 0 4 ************************
;* Title:  BCD Arithmetics
;* Version:  1.1
;* Last updated: 97.07.04
;* Target:  AT90Sxxxx (All AVR Devices)
;*
;* Support E-mail: avr@atmel.com
;*

;* DESCRIPTION
;* This Application Note lists subroutines for the following Binary Coded
;* Decimal arithmetic applications:
;*
;* Binary 16 to BCD Conversion (special considerations for AT90Sxx0x)



;***** Code

bin2BCD16:
ldi cnt16a,16;Init loop counter
clr tBCD2 ;clear result (3 bytes)
clr tBCD1  
clr tBCD0  
clr ZH ;clear ZH (not needed for AT90Sxx0x)
bBCDx_1:lsl fbinL ;shift input value
rol fbinH ;through all bytes
rol tBCD0 ;
rol tBCD1
rol tBCD2
dec cnt16a ;decrement loop counter
brne bBCDx_2 ;if counter not zero
ret  ;   return

bBCDx_2:ldi r30,AtBCD2+1;Z points to result MSB + 1
bBCDx_3:
ld tmp16a,-Z;get (Z) with pre-decrement
;----------------------------------------------------------------
;For AT90Sxx0x, substitute the above line with:
;
; dec ZL
; ld tmp16a,Z
;
;----------------------------------------------------------------
subi tmp16a,-$03;add 0x03
sbrc tmp16a,3;if bit 3 not clear
st Z,tmp16a; store back
ld tmp16a,Z;get (Z)
subi tmp16a,-$30;add 0x30
sbrc tmp16a,7;if bit 7 not clear
st Z,tmp16a; store back
cpi ZL,AtBCD0;done all three?
brne bBCDx_3 ;loop again if not
rjmp bBCDx_1  






hellomessage:   ;This is the power on/reset greeting.
.db     "2313 frequency meter  vlffmtr040713B VLF LINK   Dick Cappels"
.db $0A,$0D
.db "A=10ms,B=100ms,C=1s,D=10s,E=100s. Return=meausre, R=repetitive. "
.db $0A,$0D
.db "T=Batt timer off, !=reset, ?=diaplay menu."
.db $0A,$0D
.db "Control-A to connect, Control-B to disconnect."
.db $0A,$0D
.db "Max count = 65535, Max frequency < 2 MHz. "
.db $0A,$0D
.db $00,$00

resetmessage:    ;This is the messaging telling the user
.db "Reset initiated."  ;that the controller is being reset.
.db $00,$00


crlfmessage:    ;A carriage return and linefeed.
.db     $0A,$0D
.db     00,00


tenmsmessage:    ;The messages below acknowledge the setting of the timebase
.db "Timebase set to 10 ms Frequency is Count X100."
.db     $0A,$0D
.db     00,00

hundredmsmessage:
.db "Timebase set to 100 ms. Frequency is Count X 10 "
.db     $0A,$0D
.db     00,00
onesmessage:
.db "Timebase set to 1 s. Frequency is Count X 1."
.db     $0A,$0D
.db     00,00
tensmessage:
.db "Timebase set to 10 s. Frequency is Count  X 1/10. "
.db     $0A,$0D
.db     00,00
hundredsmessage:
.db "Timebase set to 100 s. Frequency is Count  X 1/100. "
.db     $0A,$0D
.db     00,00


Onmessage:    ;Message stating that the meter hsa been connected.
.db "Frequency Meter CONNECTED. Control-B to Disconnect. "
.db     $0A,$0D
.db     00,00


Offmessage:    ;Message stating that the meter has been disconnected.
.db "Frequency Meter DISCONNECTED. Control-A to Connect. "
.db     $0A,$0D
.db     00,00


Repetitivemessage:   ;Repetitive measurement message.
.db "Taking repetitive measurements. Send characters to interrupt. "
.db     $0A,$0D
.db     00,00



Batteryoffmessage:   ;Text message laterting that battery timer has beeen turned off.
.db "Battery Timer OFF. Cycle power or reset to enable."
.db     $0A,$0D
.db     00,00



ClearIdleTimeShort:   ;Preset idle time counters for battery timer for about 1 minute.
clr idle1
clr idle2
push temp
mov temp,presetrbglc
cpi temp,1
breq presetblgcIs1
clr temp
rjmp tempset
presetblgcIs1:
ldi temp,5
tempset:  
mov idlecompare,temp
pop temp
ret


ClearIdleTime:    ;Preset idle time counters for battery timer.
clr idle1
clr idle2
push temp
ldi temp,15   ;15 for about 3 minutes
mov idlecompare,temp
pop temp
ret


IdleTime:    ;Count up to 1,200,000 start bit samples the shut down
    ;to conserve battery (about 5 minutes).

bst flags,0   ;Skip timer if flags bit 0 is set.
brts noincidle2
inc idle1
brne noincidle2
inc idle2
cp idle2,idlecompare  
brpl sleeptime  ;If time is up, go to sleep.
noincidle2:
ret


sleeptime:
ldi temp,0   ;Shut off everyting you can, go do sleep.
out PORTB,temp  ;Make I/O ports inputs, no pullup.
out DDRB,temp
out PORTD,temp
out DDRD,temp
ldi temp,0b10000000
out ACSR,temp  ;Make sure comparitor is off.
ldi temp,0b00110000
out MCUCR,temp
sleep
rjmp sleeptime   ;This instruction should never execute.

.exit     ;Assembler will not assemble past this line of this file.






Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.