| 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. |