; Morse Decoder using 16F73
;
; Display on Port B (ASCII)
; Enable on RC7
; R/W on RC6
; Data/Command on RC5
;
; POT on A/D input to RA0 to provide speed
; Input from LM567 on RA2
;
;*******************************************************


;PIC Registers
PCL  	.EQU	$02
STATUS	.EQU	$03	;Used for Zero and Carry bits
PORTA	.EQU	$05 
PORTB	.EQU	$06
PORTC	.EQU	$07
PCLATH	.EQU	$0A
ADRES	.EQU	$1E
ADCON	.EQU	$1F

;User Registers
MARKREG	.EQU  	$20
SPACEREG  .EQU	$21

MORSE	.EQU	$24
MORSELEN	.EQU	$25

SPEED	.EQU	$28
LOOPD	.EQU	$29

T1	.EQU	$2C
T2	.EQU	$2D

;PIC Bits
W	.EQU	0
F	.EQU	1
ZERO	.EQU	2
CARRY	.EQU	0
ADON	.EQU	0
GO	.EQU	2

;User Bits
ENABLE	.EQU	7
RW	.EQU	6
DC	.EQU	5
INPUT	.EQU	2
SWITCH	.EQU	4

;*******************************************************
; Program starts here
;*******************************************************

          .ORG       $00

          GOTO	START
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP

START	BSF 	3, 5
	MOVLW	$FF	     	;
	MOVWF	PORTA	     	;Set Port A to all inputs
	CLRF	PORTB	     	;Set Port B to all outputs
	CLRF	PORTC	     	;Set Port C to all outputs
	
;Initialise A/D

	MOVLW	$04
	MOVWF	ADCON
	BCF	3, 5
	MOVLW	$40
	MOVWF	ADCON
	BSF	ADCON, 0

;Initialise Display

	MOVLW  	$28		;Initial delay (40mS)
	MOVWF	T2
I2	CALL	DELAY
	DECFSZ	T2, F
	GOTO	I2     		
	MOVLW	$30 		;Function Set
	CALL	WC
	MOVLW	$0F    		;Display On
	CALL	WC
	MOVLW	$01    		;Clear Display
	CALL	WC
	CALL 	DELAY
	CALL 	DELAY
	MOVLW	$07    		;Entry Mode
	CALL	WC
	MOVLW	$8F		;Set Cursor Position
	CALL	WC
;Display initial text	
	MOVLW	$43    		;Letter C
	CALL	WD
	CALL	DELAY
	MOVLW	$57    		;Letter W
	CALL	WD
	CALL	DELAY
	MOVLW	$20    		;Space
	CALL	WD
	CALL	DELAY
	MOVLW	$44    		;Letter D
	CALL	WD
	CALL	DELAY
	MOVLW	$65    		;Letter e
	CALL	WD
	CALL	DELAY
	MOVLW	$63    		;Letter c
	CALL	WD
	CALL	DELAY
	MOVLW	$6F    		;Letter o
	CALL	WD
	CALL	DELAY
	MOVLW	$64    		;Letter d
	CALL	WD
	CALL	DELAY
	MOVLW	$65    		;Letter e
	CALL	WD
	CALL	DELAY
	MOVLW	$72    		;Letter r
	CALL	WD
	CALL	DELAY
	MOVLW	$20    		;Space
	CALL	WD
	CALL	DELAY
	MOVLW	$20    		;Space
	CALL	WD
	CALL	DELAY



	CLRF	MORSE
	CLRF	MORSELEN
	
GETNE	BTFSS	PORTA, INPUT	;Wait for negative edge (key down)
	GOTO	GETNE
	CALL	MSPEED
	BTFSS	PORTA, INPUT	;Is key still down
	GOTO	GETNE  		;No - must have been a glitch!
DOWN	CALL	MSPEED		;Yes - so its a dot or dash
	CALL	MSPEED
	INCF	MORSELEN, F	;Must be dot or dash so increment length
	RRF	MORSE, W		;Move morse character left
	ANDLW	$FE
	MOVWF	MORSE
	BTFSS	PORTA, INPUT	;Is key still down
	GOTO	GAP2     		;No, DOT *********************CHANGED from GAP
	INCF	MORSE, F		;Yes, DASH, so add a "1" to morse character
DASH	BTFSC	PORTA, INPUT	;Wait for an edge (key released)
	GOTO	DASH
	CALL	MSPEED  		
	BTFSC	PORTA, INPUT	;Is key still up
	GOTO	DASH   		;No - must have been a glitch

	GOTO	GAP		;******************ADDED
GAP2	MOVLW	$2E
	CALL	WD
	GOTO	GAP3
GAP	MOVLW	$2D
	CALL	WD
GAP3	MOVF	SPEED, W
	
;GAP	MOVF	SPEED, W		;Yes
	MOVWF	LOOPD
M2	CALL	DELAY
	DECF	LOOPD, F		;Wait for speed * 1mS
	BTFSC	STATUS, ZERO	;Have we reached end of loop
	GOTO	M3       		;Yes - so may be intercharacter gap
	BTFSS	PORTA, INPUT	;Is key still up
	GOTO	M2   		;Yes - Keep going
	CALL	MSPEED		;No - down, so probably interbit gap
	BTFSS	PORTA, INPUT	;Is key still down
	GOTO	DOWN    		;Yes, so another dot or dash
M3	MOVF	SPEED, W		;No, possible glitch so keep waiting
	MOVWF	LOOPD
M4	CALL	DELAY
	DECF	LOOPD, F		;Wait for speed * 1mS
	BTFSC	STATUS, ZERO	;Have we reached end of loop
	GOTO	DECODE     	;Yes - so must be intercharacter gap
	BTFSS	PORTA, INPUT	;Is key still up
	GOTO	M4   		;Yes - Keep going
	CALL	MSPEED		;No - down, so interbit gap
	BTFSS	PORTA, INPUT	;Is key still down
	GOTO	DOWN   		;Yes, so another dot or dash
DECODE	INCF	MORSELEN, W	;No so must be intercharacter gap
	ANDLW	$F8
	BTFSS	STATUS, ZERO
	GOTO	ERR   	  	;More than six bits!
	MOVF	MORSELEN, W
	CALL	TABLE   		;On return, W hold ASCII character
	MOVWF	PORTB

	CALL	WD   		;****************************
	CLRF	MORSE
	CLRF	MORSELEN
	CALL	MSPEED
	BTFSC	PORTA, INPUT	;Is key pressed?
	GOTO	GETNE    		;Yes
	CALL	MSPEED		;No so may be char or word gap
	BTFSC	PORTA, INPUT	;Is key pressed?
	GOTO	GETNE    		;Yes
	CALL	MSPEED
	BTFSC	PORTA, INPUT	;Is key pressed?
	GOTO	GETNE    		;Yes
	CALL	MSPEED
	BTFSC	PORTA, INPUT	;Is key pressed?
	GOTO	GETNE    		;Yes
	CALL	MSPEED
	BTFSC	PORTA, INPUT	;Is key pressed?
	GOTO	GETNE    		;Yes
	MOVLW	$20		;No, so must be interword gap
	MOVWF	PORTB
	CALL	WD
	GOTO	GETNE
				
ERR	MOVLW	$FF
	MOVWF	PORTB
	CALL	WD
	CLRF	MORSE
	CLRF	MORSELEN
	GOTO	GETNE		

FINISH	GOTO	FINISH
				
;The idea is to:
; detect a key down edge
; wait X and test - still down = must be OK / up = glitch
; wait 2*X - still down = must be dash / up = dot
; If dash, wait for key up edge
; If dot, wait 2*X. If Down again = interbit gap so goto line 3
; If still up = interchar gap so go back to start 

;**********************************************************
;
; Write Command routine
;
;**********************************************************

WC	MOVWF	PORTB
	CLRF	PORTC
	BSF	PORTC, ENABLE
	NOP
	BCF	PORTC, ENABLE
	CALL 	DELAY
	BSF	PORTC, RW
	BSF	PORTC, DC
	RETURN

;**********************************************************
;
; Write Data routine
;
;**********************************************************

WD	MOVWF	PORTB
	MOVLW	$20
	MOVWF	PORTC
	BSF	PORTC, ENABLE
	NOP
	BCF	PORTC, ENABLE
	BSF	PORTC, RW
	RETURN

;********************************************************
;
; This file contains a 1ms Delay, which includes a read
; of the A/D convertor.
;
;********************************************************


DELAY	MOVLW	$A6
	MOVWF	T1
D1	DECFSZ	T1, F
	GOTO	D1
	BSF	ADCON, GO
	MOVLW	$A5
	MOVWF	T1
D2	DECFSZ	T1, F
	GOTO	D2
	RRF	ADRES, W
	ANDLW	$7F
	ADDLW	$0C
	MOVWF	SPEED
	RETURN	     	    

	.ORG	  $100
;***********************************************************
;
; Morse to ASCII translation tables
;
; On entry, W contains character length (0 - 6 bits)
; MORSE contains actual morse character
;
;***********************************************************

MSPEED	MOVF	SPEED, W
	MOVWF	LOOPD
M1	CALL	DELAY
	DECFSZ	LOOPD, W		;Wait for speed * 1mS
	GOTO	M1
	RETURN
	
	
TABLE	MOVLW	$01
	MOVWF	PCLATH
	MOVF	MORSELEN, W
	ANDLW	$07
	ADDWF	PCL, F
	RETLW	$00
	GOTO	TABLE1
	GOTO	TABLE2
	GOTO	TABLE3
	GOTO	TABLE4
	GOTO	TABLE5
	GOTO	TABLE6
	RETLW	$00
	
TABLE1	MOVF	MORSE, W
	ANDLW	$01
	ADDWF	PCL, F
	RETLW	$45		;E
	RETLW	$54		;T

TABLE2	MOVF	MORSE, W
	ANDLW	$03
	ADDWF	PCL, F
	RETLW	$49		;I
	RETLW	$41		;A
	RETLW	$4E		;N
	RETLW	$4D		;M

TABLE3	MOVF	MORSE, W
	ANDLW	$07
	ADDWF	PCL, F
	RETLW	$53		;S
	RETLW	$55		;U
	RETLW	$52		;R
	RETLW	$57		;W
	RETLW	$44		;D
	RETLW	$4B		;K
	RETLW	$47		;G
	RETLW	$4F		;O

TABLE4	MOVF	MORSE, W
	ANDLW	$0F
	ADDWF	PCL, F
	RETLW	$48		;H
	RETLW	$56		;V
	RETLW	$46		;F
	RETLW	$FF		;..--
	RETLW	$4C		;L
	RETLW	$FF		;.-.-
	RETLW	$50		;P
	RETLW	$4A		;J
	RETLW	$42		;B
	RETLW	$58		;X
	RETLW	$43		;C
	RETLW	$59		;Y
	RETLW	$5A		;Z
	RETLW	$51		;Q
	RETLW	$FF		;---.
	RETLW	$FF		;----

TABLE5	MOVF	MORSE, W
	ANDLW	$1F
	ADDWF	PCL, F
	RETLW	$35		;5
	RETLW	$34		;4
	RETLW	$FF		;...-.
	RETLW	$33		;3
	RETLW	$FF		;..-..
	RETLW	$FF		;..-.-
	RETLW	$FF		;..--.
	RETLW	$32		;2
	RETLW	$3D		;WAIT (=)
	RETLW	$FF		;.-..-
	RETLW	$7F		;EOM (<-)
	RETLW	$FF		;.-.--
	RETLW	$FF		;.--..
	RETLW	$FF		;.--.-
	RETLW	$FF		;.---.
	RETLW	$31		;1
	RETLW	$36		;6
	RETLW	$3D		;BREAK (=)
	RETLW	$2F		;/
	RETLW	$FF		;-..--
	RETLW	$FF		;-.-..
	RETLW	$7E		;CALL (->)
	RETLW	$3C		;(<)
	RETLW	$FF		;-.---
	RETLW	$37		;7
	RETLW	$FF		;--..-
	RETLW	$FF		;--.-.
	RETLW	$FF		;--.--
	RETLW	$38		;8
	RETLW	$FF		;---.-
	RETLW	$39		;9
	RETLW	$30		;0

TABLE6	MOVF	MORSE, W
	ANDLW	$3F
	ADDWF	PCL, F
	RETLW	$FF		;......
	RETLW	$FF		;.....-
	RETLW	$FF		;....-.
	RETLW	$FF		;....--
	RETLW	$FF		;...-..
	RETLW	$7F		;EOM(<-)
	RETLW	$FF		;...--.
	RETLW	$FF		;...---
	RETLW	$FF		;..-...
	RETLW	$FF		;..-..-
	RETLW	$FF		;..-.-.
	RETLW	$FF		;..-.--
	RETLW	$3F		;?
	RETLW	$FF		;..--.-
	RETLW	$FF		;..---.
	RETLW	$FF		;..----
	RETLW	$FF		;.-....
	RETLW	$FF		;.-...-
	RETLW	$FF		;.-..-.
	RETLW	$FF		;.-..--
	RETLW	$FF		;.-.-..
	RETLW	$2E		;STOP
	RETLW	$FF		;.-.--.
	RETLW	$FF		;.-.---
	RETLW	$FF		;.--...
	RETLW	$FF		;.--..-
	RETLW	$FF		;.--.-.
	RETLW	$FF		;.--.--
	RETLW	$FF		;.---..
	RETLW	$FF		;.---.-
	RETLW	$FF		;.----.
	RETLW	$FF		;.-----
	RETLW	$FF		;-.....
	RETLW	$FF		;-....-
	RETLW	$FF		;-...-.
	RETLW	$FF		;-...--
	RETLW	$FF		;-..-..
	RETLW	$FF		;-..-.-
	RETLW	$FF		;-..--.
	RETLW	$FF		;-..---
	RETLW	$FF		;-.-...
	RETLW	$FF		;-.-..-
	RETLW	$FF		;-.-.-.
	RETLW	$FF		;-.-.--
	RETLW	$FF		;-.--..
	RETLW	$FF		;-.--.-
	RETLW	$FF		;-.---.
	RETLW	$FF		;-.----
	RETLW	$FF		;--....
	RETLW	$FF		;--...-
	RETLW	$FF		;--..-.
	RETLW	$2C		;COMMA
	RETLW	$FF		;--.-..
	RETLW	$FF		;--.-.-
	RETLW	$FF		;--.--.
	RETLW	$FF		;--.---
	RETLW	$FF		;---...
	RETLW	$FF		;---..-
	RETLW	$FF		;---.-.
	RETLW	$FF		;---.--
	RETLW	$FF		;----..
	RETLW	$FF		;----.-
	RETLW	$FF		;-----.
	RETLW	$FF		;------

	.END
	

