;**********************************************************************
;       Filename:       picmrsrc.asm
;       Date:   Wednesday, December 30, 1998 10:28
;       File Version:   
;       Author: Lawrence Foltzer
;       Size:           365 bytes
;**********************************************************************
        list    p=16F84 ; list directive to define processor
        #include        <p16F84.inc>        ; processor specific variable definitions

        __CONFIG        _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC
; timing based on 1.12MHz RC oscillator configuration using 5.1Kohm + 100pf

;       __CONFIG        _CP_OFF & _WDT_OFF & _PWRTE_ON & _RC_OSC
; timing based on 1.12MHz RC oscillator configuration using 5.1Kohm + 100pf
;**********************************************************************
;***** application specific equates
E       equ     .4
R_W     equ     .5
RS      equ     .6
code_in equ     .7      ; PORTB,7 (also ICSPDATA and tone LED)
busy    equ     .3
BusyChk equ     B'00100000'
FuncSet41       equ     0x22    ; get its attention
FuncSet42       equ     0x20    ; get it in right mode
DisplayOn       equ     0x0c
EntryMode       equ     0x06
InitDdRam       equ     0x27
Ddra4Input      equ     B'00001111'
led     equ     .4      ; RA4 runs LED
Ddrb4Input      equ     B'10001111'
Ddrb4Output     equ     B'10000000'
ReadCntrl       equ     B'10100000'
pad1    equ     0x68    ; = 104
noise   equ     0x02    ; 16 milliseconds or less is noise
Ithres  equ     0x80
tabsize equ     .4
; optest        equ     .16

;**********************************************************************
;***** ram allocation
        ORG     0x0c

temp_w  res     1
temp_status     res     1

flags   res     1
; "flags" bit assignment follows
DitDah  equ     7       ; set (1) for DIT, clear (0) for DAH
overflow        equ     6       ; slow code can cause counter overflow

PortaImage      res     1
PortbImage      res     1

timecnt res     1       ; this is increment in the ISR
period  res     1       ; and transferred here on edge detection
thres   res     1       ; computed symbol type decision threshold

codeword        res     1       ; 1/0 representation of mickey morse

ditptr  res     1       ; pointer to ditvals buffer
ditsum  res     1
ditave  res     1
ditvals res     tabsize

dahptr  res     1       ; pointer th dahvals buffer
dahsum  res     1
dahave  res     1
dahvals res     tabsize

stack   res     1       ; available RAM
;**********************************************************************
        org     0x000
boot    goto    init
; ********************************************************************************
; this IRQ is entered every 4 milliseconds
        org     0x004
ISR     movwf   temp_w
        movf    STATUS,W
        movwf   temp_status
        incf    timecnt,1
        btfss   STATUS,Z
        goto    isrjmp
        bsf     flags,overflow
        decf    timecnt,1
isrjmp  movlw   0x74    ; 116
        movwf   TMR0
        bcf     INTCON,T0IF
exit1   movf    temp_status,W
        movwf   STATUS
        swapf   temp_w,1
        swapf   temp_w,W
        retfie
; ********************************************************************************
; morse tables follow ISR to keep them in 1st page, hopefully.
ditab   clrf    PCLATH
        movf    codeword,W
        andlw   B'00111111'
        addwf   PCL,1
        retlw   " "
        retlw   "e"
        retlw   "a"
        retlw   "i"
        retlw   "w"
        retlw   "r"
        retlw   "u"
        retlw   "s"
        retlw   "j"
        retlw   "p"
        retlw   0x5f
        retlw   "l"
        retlw   0x5f
        retlw   "f"
        retlw   "v"
        retlw   "h"
        retlw   "1"
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   0x7c    ; is "|" rather than "\" end of message
        retlw   0x5f
        retlw   0x5f    ; _ = wait
        retlw   "2"
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   "3"
        retlw   "!"     ; acknowledge
        retlw   "4"
        retlw   "5"
        retlw   0x5f
        retlw   "'"
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   "."
        retlw   0x5f
        retlw   0x5f
        retlw   0x22    ; quotation mark
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   "_"
        retlw   "?"
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   "<"     ; end of work
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f

dahtab  clrf    PCLATH
        movf    codeword,W
        andlw   B'00111111'
        addwf   PCL,1
        retlw   " "
        retlw   "t"
        retlw   "n"
        retlw   "m"
        retlw   "d"
        retlw   "k"
        retlw   "g"
        retlw   "o"
        retlw   "b"
        retlw   "x"
        retlw   "c"
        retlw   "y"
        retlw   "z"
        retlw   "q"
        retlw   0x5f
        retlw   0x5f
        retlw   "6"
        retlw   "="     ; double dash
        retlw   "/"     ; fraction bar
        retlw   0x5f
        retlw   0x5f
        retlw   ">"     ; starting signal
        retlw   "("
        retlw   0x5f
        retlw   "7"
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   "8"
        retlw   0x5f
        retlw   "9"
        retlw   "0"
        retlw   0x5f
        retlw   "-"
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   ";"
        retlw   0x5f
        retlw   0x5f
        retlw   ")"
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   ","
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   ":"
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f
        retlw   0x5f

; ********************************************************************************
; next is for xtal clock
init    movlw   0x04    ; divide XTAL OSC by 4 and then 32 for 4ms ticks
        option          ; later, load TMR0 with 256-140 and let overflow
; next is for rc clock
;init   movlw   0x02    ; divide RC OSC by 4 and then 8 for ~4ms ticks
;       option          ; later, load TMR0 with 256-140 and let overflow

        movlw   Ddra4Input
        tris    PORTA
        bcf     PORTA,led       ; on initially
        movlw   Ddrb4Input
        tris    PORTB

        clrf    PortbImage
        clrf    PortaImage
dlp1    decfsz  PortaImage,1
        goto    dlp1
        decfsz  PortbImage,1
        goto    dlp1

        call    ChkBusy

        movlw   FuncSet41
        movwf   PORTB
        call    SendCmmd

        movlw   FuncSet42
        movwf   PORTB
        call    SendCmmd
        movlw   DisplayOn
        call    SendCmmd
        movlw   EntryMode
        call    SendCmmd
        movlw   InitDdRam
        call    SendCmmd

        movlw   .13
        movwf   ditptr
        movlw   ditptr
        movwf   FSR
ilp1    incf    FSR,1
        clrf    INDF
        decfsz  ditptr,1
        goto    ilp1

        movlw   0x18
        movwf   thres

        clrf    TMR0
        clrf    flags
        clrf    INTCON
        bsf     INTCON,T0IE
        bsf     INTCON,GIE
; ********************************************************************************

        clrf    PortbImage
        clrf    PortaImage
dlp1    decfsz  PortaImage,1
        goto    dlp1
        decfsz  PortbImage,1
        goto    dlp1

        call    ChkBusy

        movlw   FuncSet41
        movwf   PORTB
        call    SendCmmd

        movlw   FuncSet42
        movwf   PORTB
        call    SendCmmd
        movlw   DisplayOn
        call    SendCmmd
        movlw   EntryMode
        call    SendCmmd




start   btfss   PORTB,code_in
        goto    start   ; receiving a tone, exit on a space
        bsf     PORTA,led
; we are now receiving a space
start2  btfsc   PORTB,code_in
        goto    start2  ; now we wait for a tone to time
; detected the start of a dit or dah
        bcf     PORTA,led       ; light LED
        clrf    timecnt ; reset timer count
db1     movlw   noise   ; debounce (db) tone edge
        subwf   timecnt,W       ; timecnt - noise
        btfss   STATUS,C
        goto    db1
w84spc1 btfss   PORTB,code_in
        goto    w84spc1 ; tone still present
; tone stopped, but this is first so we don't know what it is. we assume it is a dah!
        movf    timecnt,W
        movwf   period
        clrf    timecnt
        bsf     PORTA,led
        movlw   0x01
        movwf   codeword        ; prep for 1st symbol
        movf    thres,W
        subwf   period,W        ; period - thres
        btfsc   STATUS,C
        goto    isadah
isadit  bsf     flags,DitDah
        call    avedit
        goto    mainlp
isadah  bcf     flags,DitDah
        call    avedah
; now we wait for a tone to start so we can see what kind of space just passed
mainlp  btfsc   PORTB,code_in
        goto    mainlp  ; space while set
        movf    timecnt,W
        movwf   period
        clrf    timecnt
; we are timing the current tone period now. so light the LED.
        bcf     PORTA,led       ; let there be light
; ********************************************************************************
; so how long was the space? symbol or char
        movf    thres,W
        subwf   period,W        ; period - thres
        btfss   STATUS,C
        goto    symbolspc
        goto    longspc
longspc rlf     thres,W
        subwf   period,W        ; period - thres
        btfss   STATUS,C
        goto    charspc
        goto    wordspc
; ********************************************************************************
symbolspc       movlw   noise
db3     subwf   timecnt,W       ; timecnt - noise
        btfss   STATUS,C
        goto    db3
db4     btfss   PORTB,code_in
        goto    db4     ; wait for the tone to end
        movf    timecnt,W
        movwf   period
        clrf    timecnt
        bsf     PORTA,led
        movf    thres,W
        subwf   period,W        ; period - thres
        btfsc   STATUS,C
        goto    itsadah
        goto    itsadit
; ********************************************************************************
itsadit call    avedit
        btfsc   flags,DitDah
        bsf     STATUS,C
        btfss   flags,DitDah
        bcf     STATUS,C
        rlf     codeword,1
        goto    mainlp
; ********************************************************************************
itsadah call    avedah
        btfss   flags,DitDah
        bsf     STATUS,C
        btfsc   flags,DitDah
        bcf     STATUS,C
        rlf     codeword,1
        goto    mainlp
; ********************************************************************************
charspc btfsc   flags,DitDah
        goto    ditstart1
;       goto    dahstart1
; ********************************************************************************
dahstart1       call    dahtab
        goto    printit
; ********************************************************************************
ditstart1       call    ditab
printit call    SendText        ; printit, send to LCD
        goto    db1
; ********************************************************************************
wordspc btfsc   flags,DitDah
        goto    ditstart2
;       goto    dahstart2
dahstart2       call    dahtab
doit    call    SendText
        movlw   0x20    ; space
        call    SendText
        goto    db1
ditstart2       call    ditab
        goto    doit
; ********************************************************************************
avedit  movf    ditptr,W
        addlw   ditvals
        movwf   FSR
        movf    INDF,W
        subwf   ditsum,1
        movf    period,W
        movwf   INDF
        addwf   ditsum,1
        rrf     ditsum,W
        movwf   ditave
        rrf     ditave,1
        movlw   0x3f
        andwf   ditave,1
        incf    ditptr,1
        movlw   0x03
        andwf   ditptr,1
        goto    makethres
; ********************************************************************************
avedah  movf    dahptr,W
        addlw   dahvals
        movwf   FSR
        movf    INDF,W
        subwf   dahsum,1
        movf    period,W
        movwf   INDF
        addwf   dahsum,1
        rrf     dahsum,w
        movwf   dahave
        rrf     dahave,1
        movlw   0x3f
        andwf   dahave,1
        incf    dahptr,1
        movlw   0x03
        andwf   dahptr,1
makethres       movf    ditave,W
        subwf   dahave,W
        movwf   thres
        bcf     STATUS,C
        rrf     thres,1
        movf    ditave,W
        addwf   thres,1
        return
; ********************************************************************************
SendText        clrf    PORTB
        bsf     PORTB,RS
        goto    Send1
SendCmmd        clrf    PORTB
Send1   movwf   PortbImage
        swapf   PortbImage,w
        andlw   0x0f
        iorwf   PORTB,1
        bsf     PORTB,E
        bcf     PORTB,E
        movlw   0xf0
        andwf   PORTB,1
        movf    PortbImage,w
        andlw   0x0f
        iorwf   PORTB,1
        bsf     PORTB,E
        bcf     PORTB,E
; ********************************************************************************
ChkBusy movlw   Ddrb4Input
        tris    PORTB
SampleAgain     movlw   ReadCntrl
        movwf   PORTB
        bsf     PORTB,E
        movf    PORTB,w
        movwf   PortbImage
        bcf     PORTB,E
        bsf     PORTB,E
        bcf     PORTB,E
        btfsc   PortbImage,busy
        goto    SampleAgain
        movlw   Ddrb4Output
        tris    PORTB
        return
;**********************************************************************
; this version is based on use of an NE567 tone decoder
; as input filter. decoder output is low when a tone is detected.
; advantages: immunity to adjacent channel signal, and amplitude variation.

; timing considerations, how long is a symbol?
; the reference symbol duration is the DIT!.
; a DAH symbol is 3 DITs long.
; the space between a pair of symbols is 1 DIT long.
; characters are groups of symbols and the spaces between them.
; the space between characters is 3 DITs long.
; the space between words is 5 DITs long.
; there are 50 symbol periods in the reference string: PARIS
; ". _ _ .   . _   . _ .   . .   . . .     "
; so at 12 WPM, we have 600 symbols in 60 seconds, ===> 0.1 sec / symbol
; @ 36 WPM, the shortest (DIT) symbol period is 33ms long.
; ********************************************************************************
; ********************************************************************************
; *****************************************


        end     
