;********************************************************************** ; This file is a basic code template for object module code * ; generation on the PICmicro PIC16F648A. This file contains the * ; basic code building blocks to build upon. As a project minimum * ; the 16F648A.lkr file will also be required for this file to * ; correctly build. The .lkr files are located in the MPLAB * ; directory. * ; * ; If interrupts are not used all code presented between the * ; code section "INT_VECTOR and code section "MAIN" can be removed. * ; In addition the variable assignments for 'w_temp' and * ; 'status_temp' can be removed. * ; * ; If interrupts are used, as in this template file, the 16F648A.lkr * ; file will need to be modified as follows: Remove the lines * ; CODEPAGE NAME=vectors START=0x0 END=0x4 PROTECTED * ; and * ; SECTION NAME=STARTUP ROM=vectors * ; and change the start address of the page0 section from 0x5 to 0x0 * ; * ; Refer to the MPASM User's Guide for additional information on * ; features of the assembler and linker (Document DS33014). * ; * ; Refer to the respective PICmicro data sheet for additional * ; information on the instruction set. * ; * ;********************************************************************** ; * ; Filename: EchoPTT.asm * ; Date: 09/21/2006 * ; File Version: * ; * ; Author: Satoshi Yasuda 7m3tjz/ad6gz * ; * ; * ;********************************************************************** ; * ; Files required: * ; 16F648A.lkr * ; * ; * ;********************************************************************** ; * ; Notes: * ; * ; * ; * ; * ;********************************************************************** list p=16F648A ; list directive to define processor #include ; processor specific variable definitions errorlevel -302 ; suppress message 302 from list file __CONFIG _CP_OFF & _DATA_CP_OFF & _LVP_OFF & _BOREN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC ; '__CONFIG' directive is used to embed configuration word within .asm file. ; The lables following the directive are located in the respective .inc file. ; See data sheet for additional information on configuration word settings. ;***** VARIABLE DEFINITIONS (examples) ; example of using Shared Uninitialized Data Section INT_VAR UDATA_SHR 0x71 w_temp RES 1 ; variable used for context saving status_temp RES 1 ; variable used for context saving pclath_temp RES 1 ; variable used for context saving ; msec_cnt RES 1 msec_sw RES 1 sec_cnt RES 1 sec_sw RES 1 ptt_break RES 1 ; ptt_break time ptt_break_cnt RES 1 break_inter RES 1 ; break interrupt time break_inter_cnt RES 1 dpdt res 1 count res 1 count1 res 1 offset res 1 ;********************************************************************* sqlch_in_bit equ 2 dip_sw_port_sel equ 0x01 ptt_on_bit_pat equ 0x00 ptt_off_bit_pat equ 0x02 not_read_dip_sw equ 0x08 RS equ 0 RW equ 1 E equ 2 BUSY_F equ 7 ;********************************************************************** RESET_VECTOR CODE 0x000 ; processor reset vector goto main ; go to beginning of program INT_VECTOR CODE 0x004 ; interrupt vector location movwf w_temp ; save off current W register contents movf STATUS,w ; move status register into W register bcf STATUS,RP0 movwf status_temp ; save off contents of STATUS register movf PCLATH,w ; move pclath register into W register movwf pclath_temp ; save off contents of PCLATH register ; isr code can go here or be located as a call subroutine elsewhere bcf INTCON,T0IF ; interrupt flag clear movlw 0x3f ; load timer movwf TMR0 ; set to TMR0 ; decfsz msec_cnt,f ; 10msec counter-1 goto return_0 movlw 0x0a ; set 10 10mSec * 10 = 100mSec movwf msec_cnt incf msec_sw,f ; decfsz sec_cnt,f goto return_0 movlw 0x0a ; set 100 10mSec * 10 * 10 = 1Sec movwf sec_cnt incf sec_sw,f return_0 movf pclath_temp,w ; retrieve copy of PCLATH register movwf PCLATH ; restore pre-isr PCLATH register contents movf status_temp,w ; retrieve copy of STATUS register movwf STATUS ; restore pre-isr STATUS register contents swapf w_temp,f swapf w_temp,w ; restore pre-isr W register contents retfie ; return from interrupt main ; remaining code goes here clrf PORTA movlw 0x07 movwf CMCON bcf STATUS,RP1 bsf STATUS,RP0 ; set page 1 movlw 0x04 ; 2 bit of PortA: Input movwf TRISA ; 0,1,3,4 bits of PortA: Output movlw 0xff ; All bits of PortB: Input movwf TRISB ; bcf OPTION_REG,NOT_RBPU ; Pullup on for PortB bcf STATUS,RP0 ; set page 0 ; ; interrupt timere set for 10mSec. bsf STATUS,RP0 ; change page 1 movlw 0x87 ; counter mode set: 255 movwf OPTION_REG ; preset counter set bcf STATUS,RP0 ; change page 0 movlw 0x3f ; counter set 0x3f (19.6608MHz) ; 0x3c (20.0000MHz) movwf TMR0 ; set TMR0 bsf INTCON,T0IE ; enable timer interrupt bsf INTCON,GIE ; enable all interrupt ; ; read value of interval time from DIPSW8(SW2) movlw dip_sw_port_sel | ptt_off_bit_pat ; set interval time bit 0 movwf PORTA nop nop movf PORTB,w xorlw 0xff btfsc STATUS,Z ; if zero movlw 0x96 ; = 0 150 Sec. (default) movwf break_inter ; read value of break time from DIPSW8(SW1) movlw ptt_off_bit_pat movwf PORTA nop nop movf PORTB,w xorlw 0xff btfsc STATUS,Z ; if zero movlw 0x0f ; = 0 1.5 Sec. (default) movwf ptt_break ; movlw ptt_off_bit_pat | not_read_dip_sw movwf PORTA ; bsf STATUS,RP0 clrf TRISB ; All bits of PORTB: Output bcf STATUS,RP0 ; ; LCD init call lcd_init call lcd_busy_4 movlw b'00001100' ; clear text call lcd_cmd_4 call lcd_busy_4 call lcd_display ; ; IDLE clrf msec_sw movlw 0x0a movwf msec_cnt clrf sec_sw movlw 0x0a movwf sec_cnt movlw ptt_off_bit_pat | not_read_dip_sw ; ptt_off_bit_pattarn set movwf PORTA movf break_inter,w movwf break_inter_cnt movf ptt_break,w movwf ptt_break_cnt call lcd_display_ptt_off call lcd_display_line2_1 call lcd_display_line2_2 ; check OUT1 of njm2072d (VOX on or off) btfsc PORTA,sqlch_in_bit ; 0= on 1=off goto IDLE ; off goto ptt_on_check ; on ; VOX on ptt_on_check call lcd_display_ptt_on call lcd_display_line2_1 movlw ptt_on_bit_pat | not_read_dip_sw movwf PORTA ;@ptt_out ==> 1 nop nop btfsc PORTA,sqlch_in_bit ; 1=off 0=on goto check_break ; off goto still_ptt_on ; on still_ptt_on movf sec_sw,f ; sec_sw ? btfsc STATUS,Z ; zeror ? goto ptt_on_check break_cnt_dec decf sec_sw,f decfsz break_inter_cnt,f goto ptt_on_check goto send_break check_break call lcd_display_ptt_off movlw ptt_off_bit_pat | not_read_dip_sw movwf PORTA clrf msec_sw movf ptt_break,w movwf ptt_break_cnt check_break_cnt btfsc PORTA,sqlch_in_bit ; 1=off 0=on goto check_break_time ; = off goto ptt_on_check ; = on check_break_time call lcd_display_line2_2 movf msec_sw,f btfsc STATUS,Z ; if zero goto check_break_cnt ; = 0 decf msec_sw,f ; not = 0 decfsz ptt_break_cnt,f ; if zero goto check_break_time ; not = 0 goto IDLE ; = 0 ; insert break time send_break call lcd_display_ptt_off call lcd_display_line2_1 movlw ptt_off_bit_pat | not_read_dip_sw movwf PORTA ; send break clrf msec_sw ; clear msec_sw movf ptt_break,w movwf ptt_break_cnt send_break_loop call lcd_display_line2_2 movf msec_sw,f btfsc STATUS,Z goto send_break_loop decf msec_sw,f decfsz ptt_break_cnt,f goto send_break_loop call lcd_display_line2_2 goto IDLE ; wait new event ; ; lcd_display_ptt_on movlw b'11000001' call lcd_cmd_4 call lcd_busy_4 movlw "N" call lcd_data_4 call lcd_busy_4 movlw " " call lcd_data_4 call lcd_busy_4 return lcd_display_ptt_off movlw b'11000001' call lcd_cmd_4 call lcd_busy_4 movlw "F" call lcd_data_4 call lcd_busy_4 movlw "F" call lcd_data_4 call lcd_busy_4 return lcd_display_line2_1 ; break interval value movlw b'11000110' call lcd_cmd_4 call lcd_busy_4 movf break_inter_cnt,w sublw 0x09 btfsc STATUS,C goto lcd_display_line2_1_0 movf break_inter_cnt,w movwf count bcf STATUS,C rlf count,f bcf STATUS,C rlf count,f incf count,f andlw 0xc0 movwf count1 swapf count1,f bcf STATUS,C rrf count1,f rrf count1,f movlw LOW table addwf count,F movlw HIGH table btfsc STATUS,C addlw 1 addwf count1,w movwf PCLATH movf count,w call table call lcd_data_4 call lcd_busy_4 incf count,f btfsc STATUS,Z incf PCLATH,f movf count,w call table call lcd_data_4 call lcd_busy_4 incf count,f btfsc STATUS,Z incf PCLATH,f incf count,f btfsc STATUS,Z incf PCLATH,f movf count,w call table call lcd_data_4 call lcd_busy_4 return lcd_display_line2_1_0 ; break interval value movf break_inter_cnt,w movwf count bcf STATUS,C rlf count,f bcf STATUS,C rlf count,f incf count,f andlw 0xc0 movwf count1 swapf count1,f bcf STATUS,C rrf count1,f rrf count1,f movlw LOW table addwf count,F movlw HIGH table btfsc STATUS,C addlw 1 addwf count1,w movwf PCLATH movlw " " call lcd_data_4 call lcd_busy_4 incf count,f btfsc STATUS,Z incf PCLATH,f movlw " " call lcd_data_4 call lcd_busy_4 incf count,f btfsc STATUS,Z incf PCLATH,f incf count,f btfsc STATUS,Z incf PCLATH,f movf count,w call table call lcd_data_4 call lcd_busy_4 return lcd_display_line2_2 ; break time value movlw b'11001011' call lcd_cmd_4 call lcd_busy_4 movf ptt_break_cnt,w movwf count bcf STATUS,C rlf count,f bcf STATUS,C rlf count,f incf count,f andlw 0xc0 movwf count1 swapf count1,f bcf STATUS,C rrf count1,f rrf count1,f movlw LOW table addwf count,F movlw HIGH table btfsc STATUS,C addlw 1 addwf count1,w movwf PCLATH movf count,w call table call lcd_data_4 call lcd_busy_4 incf count,f btfsc STATUS,Z incf PCLATH,f movf count,w call table call lcd_data_4 call lcd_busy_4 incf count,f btfsc STATUS,Z incf PCLATH,f movf count,w call table call lcd_data_4 call lcd_busy_4 incf count,f btfsc STATUS,Z incf PCLATH,f movf count,w call table call lcd_data_4 call lcd_busy_4 return lcd_display movlw b'10000000' call lcd_cmd_4 call lcd_busy_4 movlw 1 movwf count lcd_display_0 movwf offset movlw LOW lcd_msg addwf offset,F movlw HIGH lcd_msg btfsc STATUS,C addlw 1 movwf PCLATH movf offset,w call lcd_msg addlw 0 btfsc STATUS,Z goto lcd_display_1 call lcd_data_4 call lcd_busy_4 incf count,f movfw count goto lcd_display_0 lcd_display_1 movlw b'11000000' call lcd_cmd_4 call lcd_busy_4 movlw "O" call lcd_data_4 call lcd_busy_4 movlw b'11001001' call lcd_cmd_4 call lcd_busy_4 movlw "s" call lcd_data_4 call lcd_busy_4 movlw b'11001111' call lcd_cmd_4 call lcd_busy_4 movlw "s" call lcd_data_4 call lcd_busy_4 return ; lcd_init call time10m call time10m movlw b'00110000' call lcd_cmd call time10m movlw b'00110000' call lcd_cmd call time100u movlw b'00110000' call lcd_cmd call time100u movlw b'00100000' call lcd_cmd call lcd_busy_4 movlw b'00101000' call lcd_cmd_4 call lcd_busy_4 movlw b'00001000' call lcd_cmd_4 call lcd_busy_4 movlw b'00000001' call lcd_cmd_4 call lcd_busy_4 movlw b'00000110' call lcd_cmd_4 return ; ; lcd_cmd_4 movwf dpdt andlw 0xf0 call lcd_cmd swapf dpdt,w andlw 0xf0 call lcd_cmd return lcd_cmd movwf PORTB bcf PORTB,RW nop bcf PORTB,RS nop bsf PORTB,E nop bcf PORTB,E return ; ; lcd_busy_4 bsf STATUS,RP0 movlw 0xf0 movwf TRISB bcf STATUS,RP0 bcf PORTB,RS nop bsf PORTB,RW nop bsf PORTB,E nop movf PORTB,w bcf PORTB,E movwf dpdt bsf PORTB,E nop movf PORTB,W bcf PORTB,E btfsc dpdt,BUSY_F goto lcd_busy_4 bcf PORTB,RW bsf STATUS,RP0 clrf TRISB bcf STATUS,RP0 return ; ; lcd_data_4 movwf dpdt andlw 0xf0 call lcd_data swapf dpdt,w andlw 0xf0 call lcd_data return lcd_data movwf PORTB bcf PORTB,RW nop bsf PORTB,RS nop bsf PORTB,E nop bcf PORTB,E return ; ; time100u movlw 0xa2 ; 19.6608MHz 0xa2 20.00MHz 0xa5 movwf count nop nop loop decfsz count,f goto loop return time10m movlw 0x64 ; 19.6608MHz 0x64 20.00MHz 0x63 movwf count1 nop nop loop1 call time100u decfsz count1,f goto loop1 return org 0x200 table movwf PCL dt " 0.0"," 0.1"," 0.2"," 0.3"," 0.4"," 0.5"," 0.6"," 0.7"," 0.8"," 0.9" dt " 1.0"," 1.1"," 1.2"," 1.3"," 1.4"," 1.5"," 1.6"," 1.7"," 1.8"," 1.9" dt " 2.0"," 2.1"," 2.2"," 2.3"," 2.4"," 2.5"," 2.6"," 2.7"," 2.8"," 2.9" dt " 3.0"," 3.1"," 3.2"," 3.3"," 3.4"," 3.5"," 3.6"," 3.7"," 3.8"," 3.9" dt " 4.0"," 4.1"," 4.2"," 4.3"," 4.4"," 4.5"," 4.6"," 4.7"," 4.8"," 4.9" dt " 5.0"," 5.1"," 5.2"," 5.3"," 5.4"," 5.5"," 5.6"," 5.7"," 5.8"," 5.9" dt " 6.0"," 6.1"," 6.2"," 6.3"," 6.4"," 6.5"," 6.6"," 6.7"," 6.8"," 6.9" dt " 7.0"," 7.1"," 7.2"," 7.3"," 7.4"," 7.5"," 7.6"," 7.7"," 7.8"," 7.9" dt " 8.0"," 8.1"," 8.2"," 8.3"," 8.4"," 8.5"," 8.6"," 8.7"," 8.8"," 8.9" dt " 9.0"," 9.1"," 9.2"," 9.3"," 9.4"," 9.5"," 9.6"," 9.7"," 9.8"," 9.9" dt "10.0","10.1","10.2","10.3","10.4","10.5","10.6","10.7","10.8","10.9" dt "11.0","11.1","11.2","11.3","11.4","11.5","11.6","11.7","11.8","11.9" dt "12.0","12.1","12.2","12.3","12.4","12.5","12.6","12.7","12.8","12.9" dt "13.0","13.1","13.2","13.3","13.4","13.5","13.6","13.7","13.8","13.9" dt "14.0","14.1","14.2","14.3","14.4","14.5","14.6","14.7","14.8","14.9" dt "15.0","15.1","15.2","15.3","15.4","15.5","15.6","15.7","15.8","15.9" dt "16.0","16.1","16.2","16.3","16.4","16.5","16.6","16.7","16.8","16.9" dt "17.0","17.1","17.2","17.3","17.4","17.5","17.6","17.7","17.8","17.9" dt "18.0","18.1","18.2","18.3","18.4","18.5","18.6","18.7","18.8","18.9" dt "19.0","19.1","19.2","19.3","19.4","19.5","19.6","19.7","19.8","19.9" dt "20.0","20.1","20.2","20.3","20.4","20.5","20.6","20.7","20.8","20.9" dt "21.0","21.1","21.2","21.3","21.4","21.5","21.6","21.7","21.8","21.9" dt "22.0","22.1","22.2","22.3","22.4","22.5","22.6","22.7","22.8","22.9" dt "23.0","23.1","23.2","23.3","23.4","23.5","23.6","23.7","23.8","23.9" dt "24.0","24.1","24.2","24.3","24.4","24.5","24.6","24.7","24.8","24.9" dt "25.0","25.1","25.2","25.3","25.4","25.5" lcd_msg movwf PCL dt "PTT EchoLink CTL",0 ; initialize eeprom locations END ; directive 'end of program'