| CODE |
;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 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) .equ PORTBdata =0b11111111;Initial data .equ DDRBdata =0b00000000;Initial data ;C0 A/D A configure as INPUT ;C1 A/D B configure as INPUT ;C2 A/D C configure as INPUT ;C3 A/D D configure as INPUT ;C4 (not assigned - configure as INPUT with weak pullup) ;C5 (not assigned - configure as INPUT with weak pullup) ;C6 (not assigned - configure as INPUT with weak pullup) ;C7 (not assigned - configure as INPUT with weak pullup) .equ PORTCdata =0b11110000;Initial data .equ DDRCdata =0b000000O0;Initial data ;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 AN0 ;D7 AN1 .equ PORTDdata =0b00000000;Initial data .equ DDRDdata =0b00000000;Initial data ;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 = 6;Pin output signal is to appear on. .equ LEDOutPort = PORTD;Indicator LED .equ LEDOutDDR = DDRD .equ LEDOutPin = 2 .equ CompPlusPort = PORTB;Comparitor noninverting input (input 0) .equ CompPlusDDR = DDRB .equ CompPlusPin = 6 .equ BridgePowerPort = PORTB;Power for voltage devider (bridging resistors) .equ BridgePowerDDR = DDRB .equ BridgePowerPin = 3 .def RFChar = r16;RF character I/O buffer (must be a high register) .def temp = r17;General purpose scratch register. .cseg .ORG $0000 ;Initializaton code rjmp start .org $0009 rjmp timer0service .org $0010 rjmp comparitorservice .include "vlfcwm8.inc" ;Include file to be in same directory as this file. start: ;Entry point after reset -initialize everything ldi temp,high(ramend) ;Initialize 16 bit Stack Pointer out sph,temp ldi temp,low(ramend) out spl,temp ldi temp,DDRBdata ;Set PORTB. out DDRB,temp ldi temp,PORTBdata out PORTB,temp ldi temp,DDRCdata ;Set PORTC out DDRC,temp ldi temp,PORTcdata out PORTc,temp ldi temp,DDRDdata ;Set PORTD. out DDRD,temp ldi temp,PORTDdata out PORTD,temp sei ;Enable interrupts. ;////////////////// END OF INITIALIZATION CODE \\\\\\\\\\\\\\\\\\\\\\\\\ .exit |
| CODE |
;File name: vlfvmtrmg8.asm ;Copyright 2004 Richard Cappels, projects@cappels.org www.project.cappels.org ;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. ; ;This code expects the controller, an ATMega8, to operate at 4 Mhz. ; ;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) .equ PORTBdata =0b11111111;Initial data .equ DDRBdata =0b00000000;Initial data ;C0 A/D A configure as INPUT ;C1 A/D B configure as INPUT ;C2 A/D C configure as INPUT ;C3 A/D D configure as INPUT ;C4 (not assigned - configure as INPUT with weak pullup) ;C5 (not assigned - configure as INPUT with weak pullup) ;C6 (not assigned - configure as INPUT with weak pullup) ;C7 (not assigned - configure as INPUT with weak pullup) .equ PORTCdata =0b11110000;Initial data .equ DDRCdata =0b000000O0;Initial data ;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 AN0 ;D7 AN1 .equ PORTDdata =0b00000000;Initial data .equ DDRDdata =0b00000000;Initial data ;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 = 6;Pin output signal is to appear on. .equ LEDOutPort = PORTD;Indicator LED .equ LEDOutDDR = DDRD .equ LEDOutPin = 2 .equ CompPlusPort = PORTB;Comparitor noninverting input (input 0) .equ CompPlusDDR = DDRB .equ CompPlusPin = 6 .equ BridgePowerPort = PORTB;Power for voltage devider (bridging resistors) .equ BridgePowerDDR = DDRB .equ BridgePowerPin = 3 .def RFChar = r16;RF character I/O buffer (must be a high register) .def temp = r17;General purpose scratch register. .def a1 = r18;Three byte number .def a2 = r19;Three byte number .def a3 = r20;Three byte number .def h = r21;Binary to decimal conversion. .def t = r22 ;Binary to decmial conversion. .def u = r23;Binary to decimal conversion. .cseg .ORG $0000 ;Initializaton code rjmp start .org $0009 rjmp timer0service .org $0010 rjmp comparitorservice .include "vlfcwm8.inc" ;Include file to be in same directory as this file. start: ;Entry point after rest -initialize everything ldi temp,high(ramend) ;Initialize 16 bit Stack Pointer out sph,temp ldi temp,low(ramend) out spl,temp ldi temp,DDRBdata ;Set PORTB. out DDRB,temp ldi temp,PORTBdata out PORTB,temp ldi temp,DDRCdata ;Set PORTC out DDRC,temp ldi temp,PORTcdata out PORTc,temp ldi temp,DDRDdata ;Set PORTD. out DDRD,temp ldi temp,PORTDdata out PORTD,temp ldi temp,0b00010101 ;ITINITALIZE A TO D CONVERTER out ADCSR,temp ;Set control and status register. 4 MHz clock. sei ;Enable interrupts. rcall Typeheader ;Type the header DefaultMain: ;Main Loop ldi RFChar,'A' rcall SendRFByte ldi RFChar,$20 rcall SendRFByte ldi temp,0 rcall measure rcall SendVolts ; rcall crlf ldi RFChar,$20 rcall SendRFByte ldi RFChar,$20 rcall SendRFByte ldi RFChar,'B' rcall SendRFByte ldi temp,1 rcall measure rcall SendVolts rcall crlf ldi RFChar,'C' rcall SendRFByte ldi RFChar,$20 rcall SendRFByte ldi temp,2 rcall measure rcall SendVolts ldi RFChar,$20 rcall SendRFByte ldi RFChar,$20 rcall SendRFByte ldi RFChar,'D' rcall SendRFByte ldi temp,3 rcall measure rcall SendVolts rcall crlf rcall Delaylots rjmp DefaultMain crlf: ;Send Carrige return and line feed ($0D, $0A) ldi RFChar,$0D rcall SendRFByte ldi RFChar,$0A rcall SendRFByte ret Typeheader: ;Type header push ZL push ZH 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 typeromstring ;Send it pop ZH pop ZL ret hellomessage: .db $0A,$0D .db $0A,$0D .db "TESTCODE" .db $0A,$0D .db $00,$00 typeromstring: ;Type on RS-232 terminal screen call with location of string in Z. push ZL ;Save Z on stack. push ZH srsa1: lpm ;Load byte from program memory into r0. tst r0 ;Check if we've reached the end of the message. breq finishsendsteringA;If so, return. mov RFChar,r0 rcall SendRFByte;Sends only via RS-232. adiw ZL,1 ;Increment Z registers rjmp srsa1 finishsendsteringA: pop ZH ;Pop Z from stack. pop ZL ret Measure:;Measure A/D channel. Enter with channel number in temp. Exit with data in YH:YL ;Allowed range is 0..5 push temp sbi ADCSR,ADEN ;Enable A/D converter. andi temp,0b00000011 ;Mask off upper bits to restrict range of channel selction. ori temp,0b01000000 ;Set reference voltage bit. out ADMUX,temp ;Select channel. sbi ADCSR,ADSC ;Start conversion. wfc: sbis ADCSR,ADIF ;Wait for bit to be set, indicating conversion complete. rjmp wfc sbi ADCSR,ADIF ;Clear interrupt flag. in YL,ADCL ;Get data into Y register. in YH,ADCH pop temp ret SendVolts: ;Enter with input value in YH:YL. YH,YL,a1,a2,a3,temp,H,T,U modified. ;Scale input with range of 0 to 1023 with a digit expression of range ;from 000 to 489. This is for a 5 volt full scale input 10 bit ADC. ;Multiply input by 489 and divide by 1,000 to get answer in tens of ;millivolts. push temp clr a1 ;Clear the 3 byte number clr a2 clr a3 mloop: tst YL brne notzero tst YH brne notzero rjmp countdone notzero: sbiw YL,1 ;Decrement the 10 bit value and add 489 to each time ldi temp,$E9 add a1,temp ;To multiply number in Y by 489 ldi temp,$01 adc a2,temp clr temp adc a3,temp rjmp mloop countdone: ;At this point, the product is in a1,2,3 clr H clr T clr U MoreH: inc H subi a1,$A0 ;Find out how many 100,000's sbci a2,$86 sbci a3,1 brcc MoreH ldi temp,$A0 ;Subtracted one too many, add back on. add a1,temp ldi temp,$86 adc a2,temp ldi temp,1 adc a3,temp dec H MoreT: inc T subi a1,$10 ;Find out how many 10.000's sbci a2,$27 sbci a3,$00 brcc moreT ldi temp,$10 ;Subtracted one too many, add back on. add a1,temp ldi temp,$27 adc a2,temp ldi temp,0 adc a3,temp dec T MoreU: inc U subi a1,$E8 ;Find out how many 10.000's sbci a2,$03 sbci a3,$00 brcc moreT ldi temp,$E8 ;Subtracted one too many, add back on. add a1,temp ldi temp,$03 adc a2,temp ldi temp,0 adc a3,temp dec U ;Convert to ASCII and send subi H,-48 ;Send Hundreds mov RFChar,H rcall SendRFByte subi T,-48 ;Send Tens mov RFChar,T rcall SendRFByte subi U,-48 ;Send Units mov RFChar,U rcall SendRFByte pop temp ret Delaylots: ;Delay 987 ms. All registers saved. push h push t push u ldi h,20 lh: clr t lt: clr u lu: dec u brne lu dec t brne lt dec h brne lh pop u pop t pop h ret .exit |