| CODE |
;Copyright 2004 Richard Cappels, projects@cappels.org ;Program Name: VLFCW -Make 181.818181818181...kHz from 4 Mhz crystal ;vlfcw040711B Changed some macros to subroutines. ;Reload and prescale values .equ XmtTimerReload = $BC;Timer 0 reload value for T .equ RcvTimerReload = $EF;Timer 0 reload value for T/4 .equ RecThresh = 40;Minimum number of counts to detect carrier. .equ Timer0Prescale = $03;Timer 0 prescaler selector .equ delaytime = 20;Waiting time after transmit mode before receiving. ;Four callable routines are available. One register isnot saved, RFByte, which is ;used to transfer the data between the RF routines and calling routines and is ;to be a high register (r16-r31). It needs to be delcared as such in program calling this file.. ;Calling other routines may result in modification of other registers. ; ;SendRFByte (subroutine) ;Sends contents of RFChar via RF. Modifies RFChar. ; ;ReceiveRFByte (subroutine) ;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. ; ;PostXmitDelay;(macro);Wait for antenna to stop ringing from xmit. ;Use this delay after transmitting if listening is to follow. The delay allows ;ringing in the antenna to die down so that the ringing is not misatken as data. ;PostRCVDelay;(macro);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 to recover. ; ; ; ; ; ; ; ; ; ; ; ;Reference circuit: ;AT90S2313 microcontroller with 4 MHz clock. ;A resonant loop antennat tuned to 182 kHz is connected across the comparitor intputs, PORTB,0 ; and PORTB,0. ;One such resonant circuit is 14 turns of #30 wire on 5.5 cm in diameter, air core, brought into ;resonance with a .033 uf capacitor in parallel with it. ;BPORTB,1 is also connected to the tap on a 2:1 resistive voltage devider. Both resistors in the ;devider are of the same vlaue and may range from about 220 Ohms to 1 k Ohms each. ;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. ;PORTB,3 is intended to drive an activity indicator LED. It goes high briefly while transmitting ;and receiving data over the RF link. ;*************Code for calling file found below .exit command, below***************** ;//////////////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: ldi r18,delaytime rcall delay ret PostRCVDelay: ldi r18, 2 * delaytime rcall delay 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 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 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 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 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/3 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 ;******************** Below is code for the calling file *****************************. ;Inlcude the code below in the calling file. It may be customized. Copy the code from here ;to ".exit" into the calling document. ;Copyright 2004 Richard Cappels, projects@cappels.org ;Program Name: VLFCW -Make 181.818181818181...kHz from 4 Mhz crystal ;////////////////// START OF INITIALIZATION CODE \\\\\\\\\\\\\\\\\\\\\\\\\ .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 .def temp = r18;General purpose scratch register. .def RFChar = r16;RF character I/O buffer ;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 (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 ;Initializaton code rjmp start .ORG $0006 rjmp timer0service ;Timer/counter compare interrupt .ORG $000A rjmp comparitorservice ;Service comparitor interupt .include "vflcw2313.inc" ;Load VLFCW routines ;Four callable routines are available. One register isnot saved, RFByte, which is ;used to transfer the data between the RF routines and calling routines and is ;to be a high register (r16-r31). It needs to be delcared as such in program calling this file.. ;Calling other routines may result in modification of other registers. ; ;SendRFByte (subroutine) ;Sends contents of RFChar via RF. Modifies RFChar. ; ;ReceiveRFByte (subroutine) ;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. ; ;PostXmitDelay;(macro);Wait for antenna to stop ringing from xmit. ;Use this delay after transmitting if listening is to follow. The delay allows ;ringing in the antenna to die down so that the ringing is not misatken as data. ;PostRCVDelay;(macro);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 to recover. ; start: ldi r16,RAMEND ;Initialize Stack Pointer. out spl,r16 ;Set PORTD. ldi temp,0b00000010 out DDRD,temp ldi temp,0b10111111 out PORTD,temp ;Set PORTB. ldi temp,0b00000000 out DDRB,temp ldi temp,0b11110100 out PORTB,temp sbi BridgePowerDDR,BridgePowerPin;Turn on bridge power sbi LEDOutDDR,LEDOutPin;Make LED so an output pin. sei ;ENABLE THE INTERRUPTS ;////////////////// END OF INITIALIZATION CODE \\\\\\\\\\\\\\\\\\\\\\\\\ .exit |
| CODE |
;rftruly040802A Minor correction - explicitly initialized DDRD. ;rftruly040731C;Fixed greeting message ;rftruly040731B;Working with RF and UART (UART has buffer). ;rftruly040731A;Working with RF receiver. ;Receive data to 16 char buffer. Write to display after time-out or return. ;Scroll after character after lf is received. Echo a null after receiving return. ; Character receive and display for Truly MTC-C162DPLY-2N 2 line X 16 char LCD. ; Requires AT90S2313 or equivalent with 4 MHz clock. ; ; Below are the connections to the Truly Display ; Pin Function (connection) ; 1 GND ; 2 VCC (+5V) ; 3 Contrast (0to +5V from wiper of 10 pot) ; 4 RS (Register Select 1=data 0=command) ; 5 R/W (tie to ground for write-only) ; 6 OE (Enable - data clocked on neg transition) ; 7-10 D0 - D3 lower 4 data bits (not used - ground these) ; 11-14 D4-D7 upper 4 data bits (connects to AVR90S2313 PB4 through PB7 respectively). ; ; The AT90S2313 routines to control the display, based on the Hitachi HD44780, and the initialization ; code in particular, are based on code originally published by Richard Hosking. ; The display is driven in the 4 bit mode. The Truly display uses a Samsung KS0070B controller ; that appears to differ from the Hitachi HD44780 controller in that the Samsung requires an ; additional 4 bit write operation during "Function set" when in 4 bit mode. This was accomplished ; by writing the "Function set" command twice to the controller twice instead of once. ; I suspect that this would work without modification with the Hitachi ; controller as the second write would be a redundant command for the Hitachi controller. ; ; Note that ; ; Below re the connections for the AT90S2313 ; Pin Function (Connection) ; VCC +5V (decoupled) ; GND ground ; XTAL1 Clock (see data sheet) ; XTAL2 Clcok (see data sheet) ; TXD Serial out (RS-232 inverting buffer to remote device - NOT USED) ; RXD Serial in (RS-232 inverting receive buffer) ; PD2-PD6 Unassigned (not connected) ; PB0,PB1 For RF link. ; PB2 R/S pin on Truly LCD (Truly module pin 4) ; PB3 OE pin on Truly LCD (Truly module pin 6) ; PB4-PB7 D4-D7 on Truly LCD (Truly module pins 11-14 respectively) ; ;definition of I/O ;B0 + comparitor input - Antenna Signal ;B1 - comparitor input - Antenna reference ;B2 Devider (bridge power) optional.MUST CHANGE ;B3 LED (high to turn LED on) MUST CHANGE . .include "2313def.inc" .def charcount =r1;Number of characters displayed on line being written .def temp =r19 ;Temporary register.(May not be R17). .def RFChar =r16;RF character I/O buffer (must be a high register) .def flagreg =r21;Flags .def gpcount =r23;Genral purpose counter (was YH in earlier version) ; YL ;UART circular buffer write ponter. ; ZL ;UART circultar buffer read pointer ; XL ;16 char line buffer pointer ;The statements below establish I/O pins needed for RF 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 = PORTD;Indicator LED .equ LEDOutDDR = DDRD .equ LEDOutPin = 4 .equ CompPlusPort = PORTB;Comparitor noninverting input (input 0) .equ CompPlusDDR = DDRB .equ CompPlusPin = 0 .equ BridgePowerPort = PORTD;Power for voltage devider (bridging resistors) .equ BridgePowerDDR = DDRD .equ BridgePowerPin = 5 .equ lbufsiz =10 .equ circbufsiz =64 .equ OE =8;Bit 3 port B display enable (also directly addressed). .equ RS =4;Bit 2 in port B display register select (also directly addressed). .equ cbufbot =$60;Bottom of circular UART receive buffer. .equ cbuftop =$67;Top of circular UART receive buffer. .equ lbufbot =$70;Bottom of display line buffer. .equ lbuftop =$7F;Top of display line buffer. ;Baudrate Calculation .equ clock = 4000000 ;clock frequency .equ baudrate = 9600 ;choose a baud rate .equ baudconstant = (clock/(16*baudrate))-1 ;Flagreg bit assignments ; bit 0 Pending linefeed if high. ; bit 1 ; bit 2 ; bit 3 ; bit 4 ; bit 5 ; bit 6 ; bit 7 ;Memory uage: ;Ring buffer from $60 through $67 ;Line buffer from $70 to $7F ;****************************** .cseg .org $00 rjmp start ;Reset .ORG $0006 rjmp timer0service ;Timer/counter compare interrupt .ORG $0007 rjmp UartRecInt .ORG $000A rjmp comparitorservice;Service comparitor interupt .include "2x16lcd.inc" .include "vlfcw2313.inc";Load VLFCW routines after last vector assignment ;but before start of application code.. HelloString:;TEXT TO BE TYPED ON FIRST LINE WHEN POWER IS APPLIED .db "9600 1 N 040802A" .db 00,00 start: ldi temp,RAMEND ;Init Stack Pointer out SPL,temp ldi temp,0b00000000;No weak pullups. out PORTB,temp ldi temp,0b11111100 out DDRB,temp;PORTB = all outputs except bits 0,1 ldi temp,0b11111111;Weak pullups on inputs out PORTD,temp ldi temp,0b00000000;PORTD - all inputs out DDRD,temp ldi flagreg,$00;Set all flags to zero. ldi temp,$00 mov charcount,temp ldi temp,baudconstant out ubrr,temp;load baudrate sbi ucr,rxen;Enable the receiver.. rcall ClearLineBuffer;Initialize line buffer. rcall InitDisplay;Initialize LCD display module, rcall sendhello;write line 1 power-up information rcall Hometwo ;Position cursor for input on line two. clr XH ;Clear XH, YH, ZY for processors with 16 bit RAM addressing clr YH clr ZH ldi YL,cbufbot;Set Y and Z circ buff pointers to bottom. ldi ZL,cbufbot sbi UCR,7 ;Enable UART Interrupt. sei ;Global interrupt flag set (enabled). forever:;Waiting for new data from circular buffer getchar: rcall ReceiveRFByte ;Wait for character to be received brcs RFcharRec ;Get waiting char from circular buffer if there is one. cp YL,ZL ;Is circular buffer read pointer alredy pointing to latest entry? breq getchar ;If so, there is no new data in the buffer. ld RFchar,Z+;If pointers are not equal, then read next char in buffer. cpi ZL,cbuftop + 1;Advance circular buffer read pointer to next value. brne NoZeroZL;If end of buffer, wrap around to start of buffer. ldi ZL,cbufbot NoZeroZL: RFcharRec: cpi RFchar,$1F;If not a control char branch to displayable char routine.. brpl ItsDisplayable cpi RfChar,$0D;If this is a carriage return character, brne noCR ;Set cursor to start of bottom line. ldi XL,lbufbot;Its a CR so set ponters back to start of line. ldi temp,$00 mov charcount,temp rcall hometwo ;Put cursor back in first column of line two. noCR: cpi RfChar,$0A;If its a linfeed char then brne NotALineFeed;set linfeed pending flag. ori flagreg,0b00000001 NotALineFeed: rjmp Buffdone ItsDisplayable:;If not a control char then do line feed if pending then ;write to display and to line buffer. sbrc flagreg,0;If linefeed i spending, then do it rcall linefeed cpi XL,lbuftop+1;Don't store if buffer at limit. breq Xfull st X+,RFchar mov temp,RFchar rcall SendData Xfull: Buffdone: Buffempty: rjmp forever SendHello:;Send HelloString rcall Homeone ldi ZH,high(2*HelloString); Load high part of byte address into ZH ldi ZL,low(2*HelloString); Load low part of byte address into ZL moretosend: 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 temp,r0 rcall SendData adiw ZL,1 ; Increment Z registers rjmp moretosend finishsendstering: ret linefeed:;Handle a linefeed char ;Clear line 1 (top line), copy line two to line one, clear ;line two, the position the cursor in first column of line two. push gpcount rcall hometwo ;Put cursor at start of line 2 so it can be cleared. ldi gpcount,$10 ;Number of chars in line. clearmore: ldi temp,$20;Fill line with spaces (erase). rcall SendData dec gpcount brne clearmore rcall homeone ;Copy line buffer to line 1, reset XL to bottom. ldi XL,lbufbot ldi temp,$00 mov charcount,temp MoreToCopy: ld temp,X+ rcall SendData cpi XL,lbuftop + 1 brne MoreToCopy rcall ClearLineBuffer andi flagreg,$0b11111100;Clear linefeed pending and enable flagsb. rcall hometwo pop gpcount ret ;Done ClearLineBuffer:;Fill line buffer with spaces, set XL to bottom. ldi XL,lbufbot ldi temp,$00 mov charcount,temp ldi temp,$20 MoreToSpace: st X+,temp cpi XL,lbuftop + 1 brne MoreToSpace ldi XL,lbufbot ret recchar: sbis usr,rxc ;Wait for a char. rjmp recchar in RFchar,udr;Read the char. ret UartRecInt:;Uart interrupt service -Write received char into a circular buffer rcall recchar ;Get the char from the UART. st Y+,RFchar cpi YL,cbuftop + 1 brne NoZeroYL2 ldi YL,cbufbot NoZeroYL2: reti |