; ; Andy Pevy AT90S1200 AVR 9k6 G4XYW modem code ; Copyright (C) 1999 Andy Pevy ; REGEN code Copyright (C) 2000 Robin Gilks ; ; This program is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation; either version 2 of the License, or ; (at your option) any later version. ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program; if not, write to the Free Software ; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ; ; V0.01 27-May-2000 ; ; andy@g4xyw.demon.co.uk ; g4xyw@g4xyw.ampr.org ; g8ecj@abmdata.demon.co.uk ; g8ecj@gb7ipd.ampr.org ; ; History ; 0.00 - Hacked out from the modem code ; 0.01 - added options to disable CWID, invert it & invert clock ; ;========================================================== ; ; This code performs the function of a regenerative repeater ; in conjunction with a full duplex G4XYW 9k6 modem ; ; It uses the Atmel AT90S1200 CPU clocked at 9.8304Mhz ; ; The DCD line at pin PB7 is monitored for activity. When ; it indicates a signal, the PTT output line at pin PB4 is ; activated. The Transmit data line at pin PB 3 has HDLC flags sent ; on it to indicate a busy condition. ; ; The Receive data is presented at pin PB2. It is then ; analyzed to extract a clock from it. ; The data is checked for valid start of frame sequence (HDLC ; flag) and once seen, data is copied across to the Transmit data ; line. On seeing bad data, the system reverts to sending flags. ; ; CW ident is also available. The values are programmed directly ; into the EEPROM at startup. ; ; The hardware for this software is compatible with the modem itself ; (ie. it can be run on a depopulated modem board with no analogue ; circuitry fitted). The PTT/DCD and TX/RX connections on the 9 pin ; connector are swapped and thats it!! ; ; To operate the regen at other than 9600bps the define 'BAUD' is ; changed in the user definable section below. This would work ; with a Baycom board for example!! ; ;========================================================== ; ; Pin definition:- ; ; Pin 1 ~RESET (pulled up internally) ; 2 PD0 OPTION_0 ; 3 PD1 OPTION_1 ; 4 XTAL2 (out) ; 5 XTAL1 (in) 9.8304Mhz ; 6 PD2 OPTION_2 ; 7 PD3 OPTION_3 ; 8 PD4/T0 OPTION_4 ; 9 PD5 OPTION_5 ; 10 0v ; 11 PD6 ~Read_options ; 12 PB0 Spare ; 13 PB1 Spare ; 14 PB2 RXin (HDLC in NRZI form) ; 15 PB3 TXout (HDLC in NRZI form) ; 16 PB4 LEDout\ ; 17 PB5 (MOSI) PTTout ; 18 PB6 (MISO) RXclock ; 19 PB7 (SCK) DCDin ; 20 Vcc ; ;================================================================= ; .DEVICE AT90S1200 ;; .NOLIST .INCLUDE "1200def.inc" .LIST ;; ;============================================================ ; morse lookup values that get put directly into EEPROM at startup ;============================================================ ;0b111111 ; 0 ----- Zero ;0b111110 ; 1 .---- One ;0b111100 ; 2 ..--- Two ;0b111000 ; 3 ...-- Three ;0b110000 ; 4 ....- Four ;0b100000 ; 5 ..... Five ;0b100001 ; 6 -.... Six ;0b100011 ; 7 --... Seven ;0b100111 ; 8 ---.. Eight ;0b101111 ; 9 ----. Nine ;0b000110 ; A .- Alpha ;0b010001 ; B -... Bravo ;0b010101 ; C -.-. Charlie ;0b001001 ; D -.. Delta ;0b000010 ; E . Echo ;0b010100 ; F ..-. Foxtrot ;0b001011 ; G --. Golf ;0b010000 ; H .... Hotel ;0b000100 ; I .. India ;0b011110 ; J .--- Juliet ;0b001101 ; K -.- Kilo ;0b010010 ; L .-.. Lima ;0b000111 ; M -- Mike ;0b000101 ; N -. November ;0b001111 ; O --- Oscar ;0b010110 ; P .--. Papa ;0b011011 ; Q --.- Quebec ;0b001010 ; R .-. Romeo ;0b001000 ; S ... Sierra ;0b000011 ; T - Tango ;0b001100 ; U ..- Uniform ;0b011000 ; V ...- Victor ;0b001110 ; W .-- Whiskey ;0b011001 ; X -..- X-ray ;0b011101 ; Y -.-- Yankee ;0b010011 ; Z --.. Zulu ;0xff ; space ;0 ; terminator ;============================================================ .equ BIT0 = 0 .equ BIT1 = 1 .equ BIT2 = 2 .equ BIT3 = 3 .equ BIT4 = 4 .equ BIT5 = 5 .equ BIT6 = 6 .equ BIT7 = 7 ;; ;================================================================= ;; .equ FLAG_DATA = 0x7e ; what a HDLC flag looks like .equ CLOCK = 9830400 ; am I really running this fast? .def millisec = r0 ; count millisecs .def ticks = r1 ; count 10mS .def seconds = r2 ; count seconds .def ten_secs = r3 ; count tens of seconds .def ditclock = r4 ; count dit time in ticks ;; .def irq_temp = r5 ; saved temp .def irq_sreg = r6 ; saved SREG ; .def txdat = r7 ; what to send out ; .def options = r8 ; option pins ;; ; option bits ; .equ NOCWID = BIT0 ; cwid disabled .equ INVCWID = BIT1 ; invert the mark/space of the CWID .equ INVRXC = BIT2 ; invert RX clock (not used but handy!!) .equ INVDCD = BIT3 ; invert DCD sense .equ ALLXFER = BIT4 ; always transfer - don't flag!! .equ SPARE4 = BIT5 ; .equ TEST_MODE = BIT7 ; set if both DCD lines tied together ;; .def pblast = r9 ; ;; .def temp = r16 ; scratch location. .def pbnow = r17 ; used to detect TXin changing. .def counter = r18 ; .def txpll = r19 ; Locks to incoming HDLC .def action = r20 ; action required ;; ; action bits ; .equ SAMPLE = BIT0 ; sample data now .equ CWID_SEND = BIT1 ; time to CWID .equ CWID_DIT = BIT2 ; one dits worth time gone by .equ XFER_FLAG = BIT3 ; if copying RX data to TX ;; .def temp1 = r21 .def delay = r22 .def flag_reg = r23 ; flag data .def cw_interval = r25 ; index into cosine lookup table. .def raw_rx = r26 ; raw incoming rx data .def rxdat = r27 ; incoming rx data NRZI decoded .def cwid_dat = r28 ; cwid bit data .def reload = r29 ; adjusted TCNT0 reload value ;; ; ; PortB pin definitions. ; .equ RXin = PB2 ; bit 2 on PORTB .equ TXout = PB3 ; bit 3 on PORTB .equ LEDout = PB4 ; bit 4 on PORTB .equ PTTout = PB5 ; bit 5 on PORTB .equ RXclock = PB6 ; bit 6 on PORTB .equ DCDin = PB7 ; bit 7 on PORTB ;; .macro set_ee ldi temp,@0 rcall write_ee .endmacro .CSEG .ORG 0 ;; ; Vectors live here.. ; rjmp reset rjmp reset rjmp TIMER_int ; reset: ; ; Called at power on/master reset. ; write the EEPROM contents with the CWID ldi temp,0 out EEAR,temp ; set up first eeprom address ;================================================================== ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ; This is where you customize the timings and CWID callsign .equ BAUD=9600 ; baud rate .equ CWID_TIME=1740 ; seconds between idents (10S granularity) .equ CWID_WPM=20 ; words per minute ; store CWID callsign where the code can access it easily ; select the relevant codes from the table above set_ee 0b001011 ; G --. Golf set_ee 0b010001 ; B -... Bravo set_ee 0b100011 ; 7 --... Seven set_ee 0b001110 ; W .-- Whiskey set_ee 0b001001 ; D -.. Delta set_ee 0 ; terminator ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ;================================================================== .equ TX_RELOAD=CLOCK/64/BAUD ; clock / 8 / baud / 8 ; PB4 has the LED on it!! ldi temp,0b00110000 ; bits 4 & 5 as output out DDRB,temp ; set up port B DDR. ldi counter,3 flash: ; three flashes of the LED - just like a KISS mode TNC!!! holding PTT off ldi temp,0b00000000 out PORTB,temp ; set LEDout low, light LED rcall delay_5s ldi temp,0b00010000 out PORTB,temp ; set LEDout high, LED off rcall delay_5s dec counter brne flash ; ; PTTout,DCDin,LEDout,RXin,TXout on Port B in bits 7-2 ldi temp,0b01111000 ; PTT,LEDout,RXclock,TXout as outputs out DDRB,temp ; set up port B DDR. ; ldi temp,0b01000000 ; 0x40 out DDRD,temp ; and port D DDR. ; ldi temp,0b00111111 ; Set PORTD6 = 0 and out PORTD,temp ; enable pullups on port D ; ldi temp,0xFF ; Wait a little delay: dec temp ; to allow the hardware brne delay ; to settle ; in temp,PIND ; read port D com temp ; invert it. andi temp,0b00111111 ; 6 bits only mov options,temp ; and save it. ; ldi temp,0b01000000 ; make PORTD6 = 1. out PORTD,temp ; ldi temp,0b01111111 ; 0x7F out DDRD,temp ; and port D DDR. ; clr temp out ACSR,temp ; set up analog comparator. out WDTCR,temp ; watchdog off out GIMSK,temp ; int0 off out WDTCR,temp ; Wdog off. ldi temp,1 mov millisec,temp ; 1mS mov ticks,temp ; 10 mS mov seconds,temp ; 1 S mov ten_secs,temp ; 10 S mov cw_interval,temp ; we should get an almost immediate CWID main: cli ; master ints off ; ldi temp,0x02 ; Set clock mode = /8 out TCCR0,temp ; ; clr action ; ldi reload,TX_RELOAD ; ldi temp,(1< 0 transition clr txpll ; hdlc input changed so reset pll counter ldi temp,-TX_RELOAD ; ensure we are starting OK out TCNT0,temp ; zero the hardware as well ; this duplicates that in the interrupt code but we might miss that one when ; - we clear the txpll variable here!! sbrc options,INVRXC ; if RX clocks to be inverted cbi PORTB,RXclock ; data stable so CLEAR T(R)Xclock sbrs options,INVRXC ; if RX clocks to be inverted sbi PORTB,RXclock ; Time for new TX data so set T(R)Xclock ; rx_2: rjmp busy_loop ; loop while in TX mode ;================================================================== ; delay .5 second - interrupts off - screws up timer setup ;================================================================== delay_5s: clr temp out TCNT0,temp ; count = 256 out TIMSK,temp ; timer ints off. ldi temp,0x05 ; Set clock mode = /1024 out TCCR0,temp ; ldi delay,17 ; number of times round the loop del_30: in temp,TIFR andi temp,(1<