;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!; ; COPYRIGHT (C) 1994 KEN STATON ; ; ALL RIGHTS RESERVED ; ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!; ; ;************************************************************************* ; ; ; PLAY MORSE CHARACTER ; INPUT: CHARACTER INDEX IN ACC ; MODIFIES REGISTERS: DPTR, ACC, R5/R6/R7 in SEND ; MODIFIES Variables: DUR ; ; DECODE SIZE: ; IF BIT 7 CLR AND BIT 6 CLR, FIVE BITS (CHARACTER IS NUMBER OR PROSIGN) ; IF BIT 7 CLR AND BIT 6 SET, SIX BITS ( CHARACTER IS PUNCTUATION OR PROSIGN) ; IF BIT 7 SET (CHARACTER IS LETTER) ; THEN IF BIT 6 CLR AND BIT 5 CLR, ONE BIT ; THEN IF BIT 6 CLR AND BIT 5 SET, TWO BITS ; THEN IF BIT 6 SET AND BIT 5 CLR, THREE BITS ; THEN IF BIT 6 SET AND BIT 5 SET, FOUR BITS ; LEFT SHIFT UNTIL SPECIFIED NUMBER OF BITS LEFT ; THEN SHIFT EACH BIT INTO CARRY & SOUND DURATION BASED ON CARRY ;MORSE CLR INT_EN ;INTS OFF MOV DPTR,#CODE_TBL MOVC A,@A+DPTR CASE1 ; IF (B7=0) AND (B6=0) {3: RLC A + 5: CALL SEND} JB ACC7,CASE2 JB ACC6,CASE2 RLC A RLC A RLC A LCALL SEND LCALL ELEM_DLY LCALL SEND LCALL ELEM_DLY LCALL SEND LCALL ELEM_DLY LCALL SEND LCALL ELEM_DLY LCALL SEND LCALL CHAR_DLY LJMP M_EXIT CASE2 ; IF (B7=0) AND (B6=1) {2: RLC A + 6: CALL SEND} JB ACC7,CASE3 JNB ACC6,CASE3 RLC A RLC A LCALL SEND LCALL ELEM_DLY LCALL SEND LCALL ELEM_DLY LCALL SEND LCALL ELEM_DLY LCALL SEND LCALL ELEM_DLY LCALL SEND LCALL ELEM_DLY LCALL SEND LCALL CHAR_DLY LJMP M_EXIT CASE3 ; IF (B7=1) AND (B6=0) AND (B5=0) {7: RLC A + 1: CALL SEND} JNB ACC7,CASE4 JB ACC5,CASE4 JB ACC6,CASE4 RLC A RLC A RLC A RLC A RLC A RLC A RLC A LCALL SEND LCALL CHAR_DLY LJMP M_EXIT CASE4 ; IF (B7=1) AND (B6=0) AND (B5=1) {6: RLC A + 2: CALL SEND} JNB ACC7,CASE5 JB ACC6,CASE5 JNB ACC5,CASE5 RLC A RLC A RLC A RLC A RLC A RLC A LCALL SEND LCALL ELEM_DLY LCALL SEND LCALL CHAR_DLY LJMP M_EXIT CASE5 ; IF (B7=1) AND (B6=1) AND (B5=0) {5: RLC A + 3: CALL SEND} JNB ACC7,CASE6 JNB ACC6,CASE6 JB ACC5,CASE6 RLC A RLC A RLC A RLC A RLC A LCALL SEND LCALL ELEM_DLY LCALL SEND LCALL ELEM_DLY LCALL SEND LCALL CHAR_DLY LJMP M_EXIT CASE6 ; IF (B7=1) AND (B6=1) AND (B5=1) {4: RLC A + 4: CALL SEND} JNB ACC7,CASE0 JNB ACC6,CASE0 JNB ACC5,CASE0 RLC A RLC A RLC A RLC A LCALL SEND LCALL ELEM_DLY LCALL SEND LCALL ELEM_DLY LCALL SEND LCALL ELEM_DLY LCALL SEND LCALL CHAR_DLY LJMP M_EXIT CASE0 LJMP M_EXIT ;ERROR HERE; SHOULD NEVER BE CASE 0 M_EXIT SETB INT_EN RET ; END MORSE ;******************************************************************* ; ; SEND SUBROUTINE ; ; INPUT IN A. RLC ONE BIT ON EXIT. ; ALSO MODIFIES R5, R6, R7 ; SEND RLC A ; PUT BIT TO SEND IN CARRY! JNC DIT_TONE ; SEND returns at DIT_TONE LJMP DAH_TONE ; or returns at DAH_TONE ; ; DIT DELAY ; Unit element. ; See page 19-4 of 1994 ARRL HANDBOOK. ; ; PARIS word length = 50 units ; Includes: ; Space between words of 7 units. ; Space btw elements is 1 unit. ; Space btw characters is 3 units. ; ; Speed (wpm) = (#dots/min)/25 ; 2 * (#dots/min) = #units/min ; #dots/min = #units/(2min) ; Speed (wpm) = (#units/min)/50 ; min = 60sec ; Speed (wpm) * 50 = (#units/min) ; Speed (wpm) * 50/60 = (#units/sec) ; Unit time = sec/#units ; Speed (wpm) * 50/60 = 1/(Unit time) ; Unit time = 1/(Speed (wpm) * 50/60) ; Unit time (mS) = (Unit time)*1000; ; Unit time (mS) = 1000/(Speed (wpm) * 50/60) ; ; Unit time (mS) = 1200/(Speed (wpm)) ; Speed (wpm) = 1200/(Unit time (mS)) ; ; Min Speed (wpm) = 255mS Unit time => (1200/0.255) = 4.7 wpm. ; Max Speed (wpm) = 20mS Unit time => (1200/0.020) = 60 wpm. ; ; Could reduce both min & max by letting fspd & cspd durations ; represent 2mS increments instead of 1mS increments...this is ; necessary for c=2.4wpm for 5@16 ; ; Farnsworth timing sends elements (dots,dashes) at a specified ; faster speed (f), then increases the delay between characters (c) ; to slow the effective rate (to s). Specify both f and s speeds. ; The actual slowed rate must be calculated (c_speed). ; ; Using PARIS as the benchmark, ; (4*3)+7=19 units are sent at c_speed, ; so 31 units are sent as f_speed. ; ; s = (f*31 + c*19)/50 ; c = (s*50 - f*31)/19 ; where f,s,c are in mS ; ; 5@16 13@18 20@23 ; f: 16 wpm = 75mS/dit | 18 wpm = 67mS/dit | 23 wpm = 52mS/dit ; s: 5 wpm = 240mS/dit | 13 wpm = 92mS/dit | 20 wpm = 60mS/dit ; c: 2.4 wpm = 509mS/dit | 9 wpm = 132mS/dit | 16 wpm = 73mS/dit ; ; 16wpm elements, 5wpm rate -> f=16, s=05, c= 2.4 (DEFAULT) ; 18wpm elements, 13wpm rate -> f=18, s=13, c= 9 ; 23wpm elements, 20wpm rate -> f=23, s=20, c= 16 ; ; CODEX word length = 60 units. ; ;******************************************************************* ; ; DIT_TONE ; DIT_TONE ; ; SINE WAVE VERSION ; MOV DUR,FSPD DIT2 ACALL SINE_CYC DJNZ DUR,DIT2 MOV P1,#DC RET ;******************************************************************* ; ; DAH_TONE = 3 * DIT ; DAH_TONE MOV R7,#3 DAH_LOOP MOV DUR,FSPD DAH2 ACALL SINE_CYC DJNZ DUR,DAH2 DJNZ R7,DAH_LOOP MOV P1,#DC RET ;******************************************************************* ; ; ELEMENT DELAY ; ELEM_DLY MOV R7,FSPD LCALL DELAY RET ;******************************************************************* ; ; CHARACTER DELAY ; CHAR_DLY MOV R5,#3 CD_LOOP MOV R7,CSPD LCALL DELAY2 DJNZ R5,CD_LOOP RET ;******************************************************************* ; ; WORD DELAY ; WORD_DLY MOV R5,#7 WD_LOOP MOV R7,CSPD LCALL DELAY2 DJNZ R5,WD_LOOP RET ;******************************************************************* ; ; DELAY FOR R7 number of mS ; Modifies R6, R7 ; DELAY D_LOOP MOV R6,#ONE_MS ; USE R6 FOR DELAY SCRATCH DJNZ R6,$ DJNZ R7,D_LOOP RET ;******************************************************************* ; ; DELAY FOR (R7 * 2) number of mS ; Used for CSPD Delays since they exceed 255 max mS count ; for R7 input to DELAY ; Modifies R6, R7 ; DELAY2 D_LOOP2 MOV R6,#ONE_MS ; USE R6 FOR DELAY SCRATCH DJNZ R6,$ MOV R6,#ONE_MS ; USE R6 FOR DELAY SCRATCH DJNZ R6,$ DJNZ R7,D_LOOP2 RET ;******************************************************************* ; ; SINE_CYC ; ; 500 Hz single cycle. 1/8 mS per step. 500 Hz -> 2 mS period. ; 2 mS / (1/8 mS / step) = 16 steps ; SINE_CYC MOV P1,#S0 MOV R6,#EIGTH_MS DJNZ R6,$ MOV P1,#S1 MOV R6,#EIGTH_MS DJNZ R6,$ MOV P1,#S2 MOV R6,#EIGTH_MS DJNZ R6,$ MOV P1,#S3 MOV R6,#EIGTH_MS DJNZ R6,$ MOV P1,#S4 MOV R6,#EIGTH_MS DJNZ R6,$ MOV P1,#S5 MOV R6,#EIGTH_MS DJNZ R6,$ MOV P1,#S6 MOV R6,#EIGTH_MS DJNZ R6,$ MOV P1,#S7 MOV R6,#EIGTH_MS DJNZ R6,$ MOV P1,#S8 MOV R6,#EIGTH_MS DJNZ R6,$ MOV P1,#S9 MOV R6,#EIGTH_MS DJNZ R6,$ MOV P1,#S10 MOV R6,#EIGTH_MS DJNZ R6,$ MOV P1,#S11 MOV R6,#EIGTH_MS DJNZ R6,$ MOV P1,#S12 MOV R6,#EIGTH_MS DJNZ R6,$ MOV P1,#S13 MOV R6,#EIGTH_MS DJNZ R6,$ MOV P1,#S14 MOV R6,#EIGTH_MS DJNZ R6,$ MOV P1,#S15 MOV R6,#EIGTH_MS DJNZ R6,$ RET ; END SINE_CYC NOP