#define x16F690 #ifdef x16F690 #include __config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF) #endif TRISKBD equ TRISC PORTKBD equ PORTC TRISSTAT equ TRISA PORTSTAT equ PORTA PORTCOLS equ PORTA TRISROWS equ TRISB PORTROWS equ PORTB LED_BIT equ 5 DIAL_SPEED_ADDR equ 0xFF ;PORTKBD equ 0x26 KBD_SCAN_SPEED equ 0x80 K_0 equ 0x00 K_1 equ 0x01 K_2 equ 0x02 K_3 equ 0x03 K_4 equ 0x04 K_5 equ 0x05 K_6 equ 0x06 K_7 equ 0x07 K_8 equ 0x08 K_9 equ 0x09 K_SEQ equ 0x0A K_RST equ 0x0B K_ENT equ 0x0C K_DEL equ 0x0D K_TKO equ 0x0E K_ABT equ 0x0F #define DIAL_SPEED_OFFSETT 0x03 DELAY MACRO DELAY_LENGTH movlw DELAY_LENGTH movwf TMP0 Delay_0 decf TMP0,f btfss STATUS,Z goto Delay_0 ENDM cblock 0x20 ROW_INDEX COL_INDEX BTN_ID KEY_ID BANK_ID TRG_BANK_ID NUM_LEN TMP0 TMP1 TMP2 COUNTER DATA_EE_ADDR DATA_EE_DATA DELAY_0 DELAY_1 DELAY_COUNTER DIAL_SPEED NUM_ARRAY:0x10 endc org 0x00 goto Main org 0x04 goto Main Main call InitPorts movlw 0xFF movwf PORTSTAT goto S_Normal IfJump MACRO KEY,STATE movlw KEY subwf KEY_ID,w btfsc STATUS,Z goto STATE ENDM S_Normal call GetKey IfJump K_ABT,S_CopyNumber IfJump K_ENT,S_WaitForID IfJump K_TKO,S_SetDialSpeed IfJump K_DEL,S_DirectDial goto S_Dial S_CopyNumber bcf PORTSTAT,LED_BIT call GetKey bsf PORTSTAT,LED_BIT IfJump K_ABT,S_Normal movf KEY_ID,w movwf BANK_ID bcf PORTSTAT,LED_BIT call GetKey bsf PORTSTAT,LED_BIT IfJump K_ABT,S_Normal movf KEY_ID,w movwf TRG_BANK_ID ; Convert BANK_ID and TRG_BANK_ID to EEPROM addresses swapf BANK_ID,w andlw 0xF0 movwf BANK_ID swapf TRG_BANK_ID,w andlw 0xF0 movwf TRG_BANK_ID ; Set the counter movlw 0x10 movwf COUNTER S_CopyNumber_CopyDigit movf BANK_ID,w movwf DATA_EE_ADDR call EEPROM_Read movf TRG_BANK_ID,w movwf DATA_EE_ADDR call EEPROM_Write incf BANK_ID,f incf TRG_BANK_ID,f decf COUNTER,f btfss STATUS,Z goto S_CopyNumber_CopyDigit goto S_Normal S_DirectDial ; Load dial speed from EEPROM movlw DIAL_SPEED_ADDR movwf DATA_EE_ADDR call EEPROM_Read movf DATA_EE_DATA,w movwf DIAL_SPEED movlw DIAL_SPEED_OFFSETT addwf DIAL_SPEED,f bcf STATUS,C rlf DIAL_SPEED,f bcf STATUS,C rlf DIAL_SPEED,f S_DirectDial_NextDigit bcf PORTSTAT,LED_BIT call GetKey bsf PORTSTAT,LED_BIT IfJump K_ABT,S_Normal IfJump K_ENT,S_Normal IfJump K_TKO,S_Normal IfJump K_DEL,S_Normal movf KEY_ID,w call DialDigit goto S_DirectDial_NextDigit S_SetDialSpeed bcf PORTSTAT,LED_BIT call GetKey bsf PORTSTAT,LED_BIT IfJump K_ABT,S_Normal movf KEY_ID,w andlw 0x07 xorlw 0x07 movwf DATA_EE_DATA movlw DIAL_SPEED_ADDR movwf DATA_EE_ADDR call EEPROM_Write goto S_Normal S_Dial ; Load dial speed from EEPROM movlw DIAL_SPEED_ADDR movwf DATA_EE_ADDR call EEPROM_Read movf DATA_EE_DATA,w movwf DIAL_SPEED movlw DIAL_SPEED_OFFSETT addwf DIAL_SPEED,f bcf STATUS,C rlf DIAL_SPEED,f bcf STATUS,C rlf DIAL_SPEED,f ; Load number from EEPROM movlw 0x10 movwf NUM_LEN swapf KEY_ID,w andlw 0xF0 movwf DATA_EE_ADDR S_Dial_DialDigit call EEPROM_Read movlw 0xFF subwf DATA_EE_DATA,w btfsc STATUS,Z goto S_Normal movf DATA_EE_DATA,w call DialDigit incf DATA_EE_ADDR,f decf NUM_LEN,f btfss STATUS,Z goto S_Dial_DialDigit goto S_Normal S_WaitForID call GetKey IfJump K_ABT,S_Normal IfJump K_ENT,S_Normal movf KEY_ID,w movwf BANK_ID clrf NUM_LEN goto S_CollectNumber S_CollectNumber bcf PORTSTAT,LED_BIT call GetKey bsf PORTSTAT,LED_BIT IfJump K_ABT,S_Normal IfJump K_ENT,S_StoreNumber movf NUM_LEN,w addlw NUM_ARRAY movwf FSR movf KEY_ID,w movwf INDF incf NUM_LEN,f movlw 0x0F subwf NUM_LEN,w btfss STATUS,Z goto S_CollectNumber goto S_StoreNumber S_StoreNumber clrf TMP0 swapf BANK_ID,w andlw 0xF0 movwf DATA_EE_ADDR movlw NUM_ARRAY movwf FSR S_StoreNumber_WriteDigit movf TMP0,w subwf NUM_LEN,w btfsc STATUS,Z goto S_StoreNumber_WriteEnd movf INDF,w movwf DATA_EE_DATA call EEPROM_Write incf FSR,f incf DATA_EE_ADDR,f incf TMP0,f goto S_StoreNumber_WriteDigit S_StoreNumber_WriteEnd movlw 0xFF movwf DATA_EE_DATA call EEPROM_Write goto S_Normal EEPROM_Read banksel DATA_EE_ADDR movf DATA_EE_ADDR,w banksel EEADR movwf EEADR banksel EECON1 bcf EECON1, EEPGD bsf EECON1, RD banksel EEDAT movf EEDAT,w banksel DATA_EE_DATA movwf DATA_EE_DATA return EEPROM_Write banksel DATA_EE_ADDR movf DATA_EE_ADDR,w banksel EEADR movwf EEADR banksel DATA_EE_DATA movf DATA_EE_DATA,w banksel EEDAT movwf EEDAT banksel EECON1 bcf EECON1, EEPGD bsf EECON1, WREN bcf INTCON, GIE movlw 0x55 movwf EECON2 movlw 0xAA movwf EECON2 bsf EECON1, WR bsf INTCON, GIE EEPROM_Write_WaitForConfirmation btfsc EECON1, WR goto EEPROM_Write_WaitForConfirmation bcf EECON1, WREN banksel DATA_EE_ADDR return InitPorts ; Initialize KBD port banksel PORTKBD clrf PORTKBD clrf PORTSTAT banksel ANSEL clrf ANSEL clrf ANSELH banksel TRISKBD movlw 0xF0 movwf TRISKBD clrf TRISSTAT clrf TRISROWS banksel PORTKBD call Mute return GetKey call KbdScan btfsc STATUS,Z goto GetKey movwf KEY_ID call KbdScan btfsc STATUS,Z goto GetKey subwf KEY_ID,w btfss STATUS,Z goto GetKey GetKey_WaitForNoKeyPressed call KbdScan btfss STATUS,Z goto GetKey_WaitForNoKeyPressed sublw 0xFF btfss STATUS,Z goto GetKey movf KEY_ID,w return KbdScan ; If button is down, returns its ID in the W register ; If no button is down, returns 0xFF in the W register and Z=1 ; If more than one btn is down, returns 0xFE in W and Z=1 movlw 0x01 movwf ROW_INDEX KbdScan_NextRow movlw 0xFF xorwf ROW_INDEX,w movwf PORTKBD DELAY KBD_SCAN_SPEED movlw 0xF0 andwf PORTKBD,w xorlw 0xF0 btfss STATUS,Z goto KbdScan_FoundKeyDown bcf STATUS,C rlf ROW_INDEX,f movlw 0x0F andwf ROW_INDEX,f btfss STATUS,Z goto KbdScan_NextRow goto KbdScan_ReturnNone KbdScan_FoundKeyDown movwf COL_INDEX swapf COL_INDEX,f clrf BTN_ID movf ROW_INDEX,w call IndexToID btfsc STATUS,Z goto KbdScan_ReturnInvalid movwf BTN_ID bcf STATUS,C rlf BTN_ID,f bcf STATUS,C rlf BTN_ID,f movf COL_INDEX,w call IndexToID btfsc STATUS,Z goto KbdScan_ReturnInvalid xorwf BTN_ID,f movf BTN_ID,w bcf STATUS,Z return KbdScan_ReturnInvalid movlw 0xFE movwf BTN_ID bsf STATUS,Z return KbdScan_ReturnNone movlw 0xFF movwf BTN_ID bsf STATUS,Z return IndexToID ; Converts the lower 4 bits of the W register to 2-bit ID; ; Sets Z flag if invalid movwf TMP0 movlw 0x0F andwf TMP0,f clrf TMP1 movlw 0x01 movwf TMP2 IndexToID_0 movf TMP2,w subwf TMP0,w btfsc STATUS,Z goto IndexToID_ReturnID incf TMP1,f movlw 0x0F andwf TMP2,w btfsc STATUS,Z goto IndexToID_ReturnInvalid bcf STATUS,C rlf TMP2,f goto IndexToID_0 IndexToID_ReturnInvalid movlw 0xFF bsf STATUS,Z return IndexToID_ReturnID movf TMP1,w bcf STATUS,Z return DialDigit andlw 0x0F call LookupDTMFPins movwf TMP0 btfss TMP0,0 bcf PORTCOLS,0 btfss TMP0,1 bcf PORTCOLS,1 btfss TMP0,2 bcf PORTCOLS,2 btfss TMP0,4 bcf PORTROWS,4 btfss TMP0,5 bcf PORTROWS,5 btfss TMP0,6 bcf PORTROWS,6 btfss TMP0,7 bcf PORTROWS,7 bcf TMP0,LED_BIT btfsc PORTSTAT,LED_BIT bsf TMP0,LED_BIT bsf PORTSTAT,LED_BIT call ToneDelay call Mute bcf PORTSTAT,LED_BIT call IntraToneDelay btfsc TMP0,LED_BIT bsf PORTSTAT,LED_BIT return Mute bsf PORTCOLS,0 bsf PORTCOLS,1 bsf PORTCOLS,2 bsf PORTROWS,4 bsf PORTROWS,5 bsf PORTROWS,6 bsf PORTROWS,7 return ToneDelay IntraToneDelay movf DIAL_SPEED,w movwf DELAY_COUNTER ToneDelayLoop call UnitDelay movf DELAY_COUNTER,f btfsc STATUS,Z return decf DELAY_COUNTER,f goto ToneDelayLoop UnitDelay movlw 0xFF movwf DELAY_0 movlw 0x03 movwf DELAY_1 UnitDelay_0 decfsz DELAY_0, f goto $+2 decfsz DELAY_1, f goto UnitDelay_0 return org 0x201 LookupDTMFPins movwf TMP0 movlw 0x02 movwf PCLATH movf TMP0,w addwf PCL,f retlw b'01111101' ; 0 retlw b'11101110' ; 1 retlw b'11101101' ; 2 retlw b'11101011' ; 3 retlw b'11011110' ; 4 retlw b'11011101' ; 5 retlw b'11011011' ; 6 retlw b'10111110' ; 7 retlw b'10111101' ; 8 retlw b'10111011' ; 9 retlw b'01111110' ; * retlw b'01111011' ; # retlw b'11111111' ; retlw b'11111111' ; retlw b'11111111' ; retlw b'11111111' ; END END