;Copyright 2004 Richard Cappels, projects@cappels.org ;Confidential - Not for distribution. ;Program Name: Send Morse ;mor040220BBeacon, version is "K60 040220B ", QRSS is 1 second dot. Fast is 83.3 ms per dot with 6 MHz clock. ;Key subroutines: ;dottime - set of delay loops to set basic dot time. Interacts with interupt routine. ;The dot time is set by adjusting the value loaded into temp at the start of the routine. ;Loading 100 into temp gives 1 wpm. Loading 1 into temp gives 100 wmp. Loadign 20 gets 5 wpm. ;sendromstring -send a string from Flash ROM. See TypeGreeting for example of use. ;sendSerialMorse - sends ASCII Data via serial port and as Morse Code. ; ldi temp,'A' ; rcall sendSerialMorse ;sendnumberMorseASCII -Sends binary nummber in temp as a 3 digit number via serial port and as Morse Code. ; ldi temp,123 ;Send the nummber, 123 ; rcall sendnumberMorseASCII ;interword - Delays one inter-word delay period ; rcall interword .include "2313def.inc" ;Include file in same directory as project. ;03e7 ;Interrupt timer parameters .equ intcountlow =$E7 ;Low byte of number of clocks between interrupts. .equ intcounthigh =$03 ;High byte of number of clocks between interrupts. ;UART baud rate calculation .equ clock = 4000000 ;clock frequency .equ baudrate = 9600 ;choose a baudrate .equ baudconstant = (clock/(16*baudrate))-1 .def delaycount = r2 ;Counter for delay generation .def dotlength = r3 ;Used to set dot length. In 1/100 sec when dotlength 2 = 20 .def dotlength2 = r4 ;Used to set dot length. .def temp = r16 ;General purpose scratch register. .def temp2 = r17 ;General purpose scratch register. .def h = r22 ;Binary to decimal conversion. .def t = r23 ;Binary to decmial conversion. .def u = r24 ;Binary to decimal conversion. .def flagreg = r25 ;Flags. ;definiton of flagreg bit assignments ;0 Status of code out bit last sent (memory used to toggle) ;1 True enables toggling of code output ;2 ;3 ;4 ;5 ;6 ;7 .equ codeport = PORTB .equ codeout = DDRB .equ codebit = 2 .equ pulsebit = 3 ;definition of I/O ;B0 + comparitor input ;B1 - comparitor input ;B2 Tone (code) output ;B3 Morse Code Key Pulses Out (positive corresponds with tone). ;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 Reserved FOR UART RECEIVE ;D1 Reserved FOR UART TRANSMIT -input has 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 ;Initializaton code rjmp start .ORG $0004 rjmp timerservice ;Timer/counter compare interrupt handler 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,0b00001100 out DDRB,temp ldi temp,0b11110011 out PORTB,temp clr flagreg ;Clear flagreg (flag register). ;UART SETUP. ldi temp,baudconstant out ubrr,temp ;Load baudrate. sbi ucr,rxen ;Enable WAUT receive ;Uart receive not used so not enabled bere. sbi ucr,txen ;Enable UART Transmit. ;TIMER 1 SETUP. ldi temp,$09 ;Set timer 1 to reset 0000 after compare match. Prescaler = 1X. out TCCR1B,temp ldi temp,intcounthigh ;Set compare register to establish interrupt frequency. out OCR1AH,temp ldi temp,intcountlow out OCR1AL,temp ldi temp,$40 ;Enable interrupt on compare match. out TIMSK,temp sei ;Enable interrupts. ldi temp,$1E ;Set up for 83 millisecond dot period. mov dotlength,temp ldi temp,$14 mov dotlength2,temp rcall TypeGreeting ;Send greeting twice rcall TypeGreeting Main: ldi temp,$1E ;Set up for 83 millisecond dot period. mov dotlength,temp ldi temp,$14 mov dotlength2,temp rcall TypeMessage ;Send message three times. rcall TypeMessage rcall TypeMessage ldi temp,30 ;Set to 1 second dot period. mov dotlength,temp ldi temp,252 mov dotlength2,temp rcall interword rcall TypeMessage ;Send message once rcall interword ; ldi temp,123 ;Send the nummber, 123 ; rcall sendnumberMorseASCII rjmp main ;Main: rcall recchar push temp rcall emitchar pop temp rcall SendMorseAscii ;emitchar rjmp Main TypeGreeting: ;Type greeting 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 sendromstring ;Send it pop ZH pop ZL ret hellomessage: .db "K60 040220B " ; .db " A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 " ; .db "0 1 2 3 4 5 6 7 8 9 " .db $0A,$0D .db $00,$00 TypeMessage: ;Type greeting push ZL push ZH ldi ZH,high(2*Message) ;Load high part of byte address into ZH ldi ZL,low(2*Message) ;Load low part of byte address into ZL rcall sendromstring ;Send it pop ZH pop ZL ret Message: .db "K60 " .db $0A,$0D .db $00,$00 sendromstring: ;call with location of string in Z. push ZL ;Save Z on stack. push ZH srs1: 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 sendSerialMorse ;Send via serial link and as Morse Code. adiw ZL,1 ;Increment Z registers rjmp srs1 finishsendstering: pop ZH ;Pop Z from stack. pop ZL rcall interword ret sendcodedcode: ;Send Coded Morse Code ;Shift out morse code from coded character. ;Enter with code for character in temp. ;Description of data format from David Robinson's web page: ;"At this point I was reminded of the N1KDO NHRC-2 repeater controller published ;in February 97 QST that had Morse ID. Investigation of the assembler listing (1) ;revealed a simple conversion scheme, where all morse characters are encoded in a ;single Byte, bitwise, LSB to MSB.; “0” = dit, “1” = dah. The Byte is shifted out ;to the right, until only a “1” remains. As an example 3 is encoded as binary 00111000, ;which translates to 38 in hexadecimal. " morecode: cpi temp,0b00000001 breq codedcodesent clc ror temp brcs senddash ;Send a dash if lsb was a one rcall dot ;Send a dot if lsb was not a one rjmp morecode senddash: rcall dash rjmp morecode codedcodesent: ;Finished sending the coded code. ret SendMorseAscii: ;Look up coded Morse code and send, followed by rcall to interchar. ;Enter with ASCII character in temp. Upper-case, don't process ;control characters. push ZL push ZH cpi temp,$20 ;If space character, do interword delay. brne SMA1 rcall interword rjmp lookupdone SMA1: cpi temp,$5B brmi upperacse andi temp,$5F ;Make upper-case upperacse: cpi temp,$2A brmi lookupdone ;Set up pointer into codechart. ldi ZH,high(2*codechart);Load high part of byte address into ZH. ldi ZL,low(2*codechart) ;Load low part of byte address into ZL. subi temp,$2A ;Removed offset from ASCII value in temp. add ZL,temp ;Add the value to the index. clr temp adc ZH,temp lpm ;Fetch the value from the table. mov temp,r0 rcall sendcodedcode ;Send as Morse Code rcall interchar ;Dealy one interchar time lookupdone: pop ZH pop ZL ret ;Return dot: ;Send dot, wait one dot time. sbr flagreg,0b00000010 ;Set flag to send tone. sbi codeport,pulsebit ;Set on-off key pulse high. rcall dottime cbr flagreg,0b00000010 ;Clear flag to send tone. cbi codeport,pulsebit ;Set on-off key pulse low. rcall dottime ret dash: ;Send dash, wait one dot time. sbr flagreg,0b00000010 ;Set flag to send tone. sbi codeport,pulsebit ;Set on-off key pulse high. rcall dottime rcall dottime rcall dottime cbr flagreg,0b00000010 ;Clear flag to send tone. cbi codeport,pulsebit ;Set on-off key pulse low. rcall dottime ret interchar: ;Wait interchear period with output off -3 dot times rcall dottime rcall dottime rcall dottime ret interword: ;Wait interword period with output off-6 dot times rcall dottime rcall dottime rcall dottime rcall dottime rcall dottime rcall dottime rcall dottime ret dottime: ;Delay one dot time. ;reload values for 100 wmp with 6 MHz Crystal: push temp push temp2 mov temp,dotlength ; 1 moretime3: clr delaycount moretime2: mov temp2,dotlength2 moretime1: dec temp2 brne moretime1 dec delaycount brne moretime2 dec temp brne moretime3 pop temp2 pop temp ret emitchar: ;Send character contained in temp with two stop bits. sbis usr,udre ;wait until the register is cleared. rjmp emitchar cbi ucr,0 ;Set 9th bit to zero (second stop bit). sbi ucr,2 ;Set to send 9 data bits. out udr,temp ;send the character. ret recchar: ;Get incoming character into temp sbis usr,rxc ;wait for a byte rjmp recchar in temp,udr ;read ret ;go back sendSerialMorse: ;Send ASCII Character via serial port and via Morse Code. ;Enter with char in temp. push temp rcall emitchar pop temp rcall SendMorseAscii ret sendnumberMorseASCII: ;Enter with value to be sent in temp, sends as three digit ascii ;via serial port and Morse code. mov U,temp ;Enter with 8 bit value in U, Exits with numerals in H,T,U clr H ;(Hundreds, Tens, and Units). clr T anotherh: subi U,100 ;Find out how many hundreds in U. brcs hdone inc H rjmp anotherh hdone: subi U,-100 ;Subtracted one too many -add back. anothert: subi U,10 brcs tdone inc T rjmp anotherT tdone: subi U,-10 cpi H,0 breq dontsendh subi H,-48 mov temp,H rcall sendSerialMorse cpi t,0 brne dontsendh ldi temp,$30 ;If U=0 then don't emit this zero rcall sendSerialMorse dontsendh: cpi t,0 breq dontsendt subi T,-48 mov temp,T rcall sendSerialMorse dontsendt: subi U,-48 mov temp,U rcall sendSerialMorse rcall interword ret codechart: ;Coded Morse Code look up table. Use ASCII value -$30, so zero = 0, "A" = $11, etc. ;Note: Some ASCII characters are silent, and are coded as 0b00000001 ;Also note: BT (pause) is coded for ASCII "<" and SK (end of contanct) is coded for ASCII "*", ;and End of Message is coded for ASCII "+". ; * (SK) + (End of Message) .db 0b01101000, 0b00101010 ; ,(comma) - . / .db 0b01110011,0b1011110,0b01111010,0b00101001 ; 0 1 2 3 .db 0b00111111,0b00111110,0b00111100,0b00111000 ; 4 5 6 7 .db 0b00110000,0b00100000,0b00100001,0b00100011 ; 8 9 : ; .db 0b00100111,0b00101111,0b01000111,0b01010101 ; < (BT) = > ? .db 0b000110001,0b00000001,0b00000001,0b01001100 ; @ A B C .db 0b00000001,0b00000110,0b00010001,0b00010101 ; D E F G .db 0b00001100,0b00000010,0b00010100,0b00001011 ; H I J K .db 0b00010000,0b00000100,0b00011110,0b00001101 ; L M N 0 .db 0b00010010,0b00000111,0b00000101,0b00001111 ; P Q R S .db 0b00010110,0b00011011,0b00001010,0b0001000 ; T U V W .db 0b00000011,0b00001100,0b00011000,0b00001110 ; X Y Z [ .db 0b00011001,0b00011101,0b00010011,0b00000001 timerservice: ;Service Timer 1 push temp in temp,sreg push temp sbrs flagreg,1 rjmp notoggle ;Toggle tone output sbi codeout,codebit ;Enable code output pin. mov temp,flagreg ;Toggle it, using flagreg 0 as memory of last one. andi temp,0b00000001 inc temp andi temp,0b00000001 brne codehigh cbi codeport,codebit andi flagreg,0b11111110 rjmp toggledone codehigh: sbi codeport,codebit ori flagreg,0b00000001 toggledone: pop temp out sreg,temp pop temp reti ;Return from interrupt. notoggle: ;Don't toggle port, but delay to equalize interrupt time toggling and not toggling. cbi codeout,codebit ;Disable code out pin. nop nop nop nop nop nop rjmp toggledone