;********************************************************************** ; Filename: picmrsrc.asm ; Date: Wednesday, December 30, 1998 10:28 ; File Version: ; Author: Lawrence Foltzer ; Size: 365 bytes ; Modified: 12/2/2007 KC2NDA - For use with 16F84A and fixed compile errors ; Modified: 6/12/2009 by "curious" - for use with 24x2 (or any other double row) display ;********************************************************************** list p=16F84A ; list directive to define processor #include ; processor specific variable definitions __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC ; timing based on 4mhz HS oscillator configuration ; __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 #EntryMode equ 0x07 LCD_dual_row equ 0x28 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 noise equ 0x01 ; 02 hex 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 chars_left res 1 ; characters already printed out ; (multi-row displays) chars_per_row equ 0x18 ; amount of chars per row lines_left res 1 ; lines already printed out lines_per_display equ 2 ; amount of lines display have ;********************************************************************** org 0x000 boot goto init ; ******************************************************************************** ; this IRQ is entered every 4ms 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 isrjmp movlw 0x79 ; 127 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 ; next is for 8mhz xtal init movlw 0x05 ; divide XTAL OSC by 4 and then 32 option ; later, load TMR0 with 256-140 and let overflow (127 for 4mhz to 4ms) movlw Ddra4Input tris PORTA bcf PORTA,led ; on initially movlw Ddrb4Input tris PORTB clrf chars_left 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 LCD_dual_row call SendCmmd movlw 0x01 ; clear display call SendCmmd movlw 0x0f ; turn on blinking block cursor call SendCmmd movlw chars_per_row movwf chars_left movlw lines_per_display movwf lines_left 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 ; ******************************************************************************** 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 ;db1loop movlw noise ; debounce (db) tone edge 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 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 decfsz chars_left return movlw chars_per_row movwf chars_left movlw 0xc0 ; set cursor back at 2nd line call SendCmmd ;fixme - progress line instead? decfsz lines_left return movlw lines_per_display movwf lines_left movlw 0x80 ; set cursor back at 1st line call SendCmmd return SendText2 clrf PORTB bsf PORTB,RS goto Send2 clrf PORTB SendCmmd clrf PORTB Send2 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 ; ******************************************************************************** ChkBusy2 movlw Ddrb4Input tris PORTB SampleAgain2 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 SampleAgain2 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