;----------------------------------------------------------------------;
; MORSE4M.ASM Send numbers 0-9 in morse code to speaker and LEDs ;
;----------------------------------------------------------------------;
; -[spkr]- = piezo speaker .-----------.
; -|RA2 RA1|- V+ = 4.5 or 5 Volts
; gnd --[spkr]--[R]--|RA3 RA0|- X = 4 MHz cer. res.
; -[R]- = 100 ohm -|RA4 OSC1|--|X|___ gnd
; -{r}- = 470 ohm V+ ---|MCLR OSC2|--|X|
; -|<- = LED gnd ---|Vss Vdd|--- V+
; gnd ---|<--{r}--|RB0 RB7|-
; gnd ---|<--{r}--|RB1 RB6|-
; gnd ---|<--{r}--|RB2 RB5|-
; gnd ---|<--{r}--|RB3 RB4|---[PB]--- gnd
; '-----------'
; PIC16F84 -[PB]- pushbutton
LIST P=16F84 ; tells which processor is used
INCLUDE "p16f84.inc" ; defines various registers etc. Look
ERRORLEVEL -224 ; suppress annoying message from tris
__CONFIG _PWRTE_ON & _XT_OSC & _WDT_OFF ; config. switches
#DEFINE pushbutton PORTB, 4 ; pushbutton on RB4 to ground
#DEFINE speaker PORTA, 3 ; piezo speaker RA3 thru 100 ohm
; to ground
CBLOCK H'C'
temp ; a temporary variable
bitcount ; counter for bits
nbr ; holds current number to send
cntmsec ; used in generating msec delays
sndcnt ; used in gerating sound
ENDC
ORG 0 ; start at location 0
goto main ; jump over to main routine
;----------------------------------------------------------------------;
; Use W to convert number in W to pattern needed to send # ;
;----------------------------------------------------------------------;
pattern:
addwf PCL, f ; PCL points to the first entry in the table
dt H'1F',H'0F',H'07',H'03',H'01',H'00',H'10',H'18',H'1C',H'1E'
; 0 1 2 3 4 5 6 7 8 9
;----------------------------------------------------------------------;
; Sound routine lasting about 100 milliseconds ;
;----------------------------------------------------------------------;
snd1:
movlw D'50' ; 50 on - off cycles
movwf sndcnt
sndloop:
bsf speaker ; RA3 high
call msec1 ; 1 msec high
bcf speaker ; RA3 low
call msec1 ; 1 msec low
decfsz sndcnt, f ; finished?
goto sndloop ; no
return ; yes
;----------------------------------------------------------------------;
; Output number in W to LEDs on Port B and to spkr on RA3 ;
;----------------------------------------------------------------------;
sendnbr:
movwf PORTB ; display number on LEDs
call pattern ; get pattern of dits and dahs
movwf temp ; save it
movlw 5 ; total of 5 dits or dahs ...
movwf bitcount ; into a counter
bitloop: btfss temp, 4 ; check 5th bit, if it is 1, send dah
call dit ; else it is 0, send dit
btfsc temp, 4 ; and skip next instruction
call dah ; get here only if bit 5 is 1
rlf temp, f ; rotate left once giving new bit 5
decfsz bitcount, f ; are we finished?
goto bitloop ; no, send new bit 5
clrf PORTB ; yes, turn display off
return
;----------------------------------------------------------------------;
; Dit routine ;
;----------------------------------------------------------------------;
dit
call snd1 ; 100 msec of tone
movlw D'100' ; followed by 100 msec of silence
call nmsec
return
;----------------------------------------------------------------------;
; Dah routine ;
;----------------------------------------------------------------------;
dah:
call snd1 ; 100 msec of tone
call snd1 ; stretch it to 300 msec
call snd1
movlw D'100' ; and 100 msec of silence
call nmsec
return
;----------------------------------------------------------------------;
; Wait until button on RB4 is released ;
;----------------------------------------------------------------------;
waitup:
btfss pushbutton ; test RB4
goto $ -1 ; ck again if pressed
movlw D'10'
call nmsec ; wait 10 msec for debounce
btfss pushbutton ; check again, still up?
goto waitup ; no start over
return ; yes, finished
;----------------------------------------------------------------------;
; Initialization Subroutine ;
;----------------------------------------------------------------------;
init:
movlw 0 ; RA0 - RA4 outputs
tris PORTA
movlw H'10' ; all outputs except RB4 input
tris PORTB ; on port B
movlw H'0' ; all outputs low (off)
movwf PORTB
movwf PORTA
option ; pullups enabled
return
;----------------------------------------------------------------------;
; Main routine, sends a new number each time button pressed ;
;----------------------------------------------------------------------;
main:
call init ; set up ports etc
start: clrf nbr ; start with nbr = 0
mainloop: call waitup
btfsc pushbutton ; wait on button press
goto $ -1
movf nbr, W ; get number into W
call sendnbr ; and output it
incf nbr, f ; set up for next number
movlw H'0A' ; reached 10?
subwf nbr, W
btfss STATUS, Z ; yes start again at 0
goto mainloop ; no, wait for next button press
goto start
;----------------------------------------------------------------------;
; time delay routines ;
;----------------------------------------------------------------------;
micro4 addlw H'FF' ; subtract 1 from 'W'
btfss STATUS,Z ; skip when you reach zero
goto micro4 ; more loops
return
;*** N millisecond delay routine ***
msec1: movlw 1 ; delay for one millisecond
nmsec: movwf cntmsec ; delay for N (in W) millisec
msecloop: movlw D'248' ; 1 usec for load
call micro4 ; this instruction is 995 usec
nop ; 1 usec
decfsz cntmsec, f ; 1 usec, (2 if skip taken)
goto msecloop ; 2 usec, loop = 995+5 = 1 msec
return
end