; DTMF REMOTE CONTROL ; ; (c) 2003 Radu Constantinescu ; constantinescuradu @yahoo.com ; RELEASED UNDER GNU PUBLIC LICENSE ; ; SOFTWARE DTMF DECODER ; modified Goertzel algorithm ; timer 2 used to generate interupts at 9765.625hz ; PWM1 output at 19531.25hz NOT USED ; ; ; Use 255 samples table ; FOR 16F87X / 20 Mhz ; F sample = 5000000/512 hz = 9765. 625 hz ; ; ; RC0 BEEP OUT ; RC1 DTMF Signal Input - Schmitt trigger ; RC2 PWM1 OUT/ not used ; RC3 HOOK ON OUT ; ; RB0 = OUTPUT1 ; RB1 = OUTPUT2 ; RB2 = OUTPUT3 ; RB3 = OUTPUT4 ; ; #PASS#1-4#0-1## SET OUTPUT ; #PASS#1-4## VERIFY OUTPUT ; #PASS#NEWPASS#NEWPASS## CHANGE PASS ; PASS IS 10 DIGITS LONG ; ; ; ; ;Started 9/1/02 ; ; ; ; #include Bank0: MACRO bcf STATUS, RP0 bcf STATUS, RP1 ENDM Bank1: MACRO bsf STATUS, RP0 bcf STATUS, RP1 ENDM Bank2: MACRO bcf STATUS, RP0 bsf STATUS, RP1 ENDM Bank3: MACRO bsf STATUS, RP0 bsf STATUS, RP1 ENDM ;**************************** ; ;User Variables ; ;**************************** COUNT EQU H'27' RESULT EQU H'28' FLAGS EQU H'29' EE_Byte EQU H'2A' ; variable for EEwrite ;2b ;2c ;2e ;2f A697SIN EQU H'30' A697COS EQU H'31' ; ACC A770SIN EQU H'32' A770COS EQU H'33' ; ACC A852SIN EQU H'34' A852COS EQU H'35' ; ACC A941SIN EQU H'36' A941COS EQU H'37' ; ACC A1209SIN EQU 0X38 A1209COS EQU 0X39 ;ACC A1336SIN EQU 0X3A A1336COS EQU 0X3B ;ACC A1447SIN EQU 0X3C A1447COS EQU 0X3D ;ACC A1633SIN EQU 0X3E A1633COS EQU 0X3F ;ACC SAMPLEBIT EQU 0X40 FSR_SAVE_DTMF EQU 0X41 ; DTMF START ROUTINE TEMP TEMP_VAL EQU 0X42 TABLECOUNTER EQU 0X43 TEMP_TIMES EQU 0X44 LOWTEMPLATE EQU 0X45 HIGHTEMPLATE EQU 0X46 BYTE EQU 0X47 RESULT1 EQU 0X48 ; DECODED DIGIT OR 0 PCLATH_SAVE EQU 0X49 W_TEMP EQU 0X4A STATUS_TEMP EQU 0X4B FSR_SAVE EQU 0X4C TIME0 EQU 0X4D ;TIMEOUT LSB TIME1 EQU 0X4E TIME2 EQU 0X4F ;TIMEOUT MSB #DEFINE DONE FLAGS,0 #DEFINE TIMEOUT FLAGS,1 #DEFINE BEEP FLAGS,2 ; Utility routines variables CBLOCK 0x50 scrA: 1 ; scratch pad 0X50 scrB: 1 scrC: 1 scrD: 1 count_1:1 ; counter lsb count_2:1 count_3:1 count_4:1 ; counter msb dig_10: 1 ; display digit 10 dig_9: 1 ; display digit 9 dig_8: 1 ; display digit 8 dig_7: 1 ; display digit 7 dig_6: 1 ; display digit 6 dig_5: 1 ; display digit 5 dig_4: 1 ; display digit 4 dig_3: 1 ; display digit 3 dig_2: 1 ; display digit 2 dig_1: 1 ; display digit 1 dig_0: 1 ; end of string 0 0X62 PSS0: 1 ;PASSWORD PSS1: 1 ;PASSWORD PSS2: 1 ;PASSWORD PSS3: 1 ;PASSWORD PSS4: 1 ;PASSWORD PSS5: 1 ;PASSWORD PSS6: 1 ;PASSWORD PSS7: 1 ;PASSWORD PSS8: 1 ;PASSWORD PSS9: 1 ;PASSWORD ENDC CBLOCK 0x72 ; variables for all the RAM pages comA: 1 comB: 1 comC: 1 comD: 1 ENDC ;*********************************************** ;EEprom Variables ;*********************************************** OUT0 EQU 0X0 PASS0 EQU 0X8 PASS1 EQU 0X9 PASS2 EQU 0XA PASS3 EQU 0XB PASS4 EQU 0XC PASS5 EQU 0XD PASS6 EQU 0XE PASS7 EQU 0XF PASS8 EQU 0X10 PASS9 EQU 0X11 ORG h'2100' ;EEPROM INITIAL VALUES DE 0,0,0,0,0,0,0,0 DE "1234567890" ;************************************************ ORG 0X00 NOP NOP CLRF STATUS ; ENSURE BANK0 GOTO START ;GOTO STARTPLUS INTERRUPT_VECTOR ORG 0X04 ;**************************** ; ; CONTEXT SAVE ; ;**************************** C_SAVE MOVWF W_TEMP SWAPF STATUS,W CLRF STATUS ;ENSURE BANK0 SAVE MOVWF STATUS_TEMP MOVF PCLATH,W ; SAVE PCLATH MOVWF PCLATH_SAVE MOVF FSR, W MOVWF FSR_SAVE BTFSS PIR1,TMR2IF ; Exit ISR if it wasn't a TMR2 Overflow GOTO C_RESTORE BCF PIR1,TMR2IF ; RESET TIMER 2 INT FLAG BTFSC TIMEOUT ; CHECK IF NOT TIMEOUT GOTO CONTIN1 ; DECREMENT TIMEOUT COUNTER DECF TIME0, F BTFSS STATUS, Z GOTO CONTIN1 ; TIME0<>0 DECF TIME1, F BTFSS STATUS, Z GOTO CONTIN1 ; TIME1<>0 BSF TIMEOUT ; SET TIMEOUT=TRUE CONTIN1: ; BEEP COUNTER BTFSS BEEP ; CHECK IF NOT BEEP GOTO CONTIN2 DECF scrA,F BTFSS STATUS, Z GOTO CONTIN2 movlw 1 xorwf PORTC, F ; flip port C0 MOVF TIME2, W ; RELOAD DELAY MOVWF scrA CONTIN2: BTFSC DONE GOTO C_RESTORE ; Skip if done ;***************************** ;TEST LEVEL of RC1 and set BYTE CLRF BYTE BTFSS PORTC, 1 GOTO CONTINUE PIN_HIGH COMF BYTE, F CONTINUE ;***************************** ; ;Get the expected Lowband Bits ; ;***************************** MOVLW LOW LOWBAND ADDWF TABLECOUNTER,W MOVLW HIGH LOWBAND BTFSC STATUS,C ADDLW 1 MOVWF PCLATH MOVF TABLECOUNTER,W CALL LOWBAND CLRF PCLATH MOVWF LOWTEMPLATE MOVF BYTE,W XORWF LOWTEMPLATE, F ; APPLY INPUT OVER MASK ;***************************** ; ;Get the expected Highband Bits ; ;***************************** MOVLW LOW HIGHBAND ADDWF TABLECOUNTER,W MOVLW HIGH HIGHBAND BTFSC STATUS,C ADDLW 1 MOVWF PCLATH MOVF TABLECOUNTER,W CALL HIGHBAND CLRF PCLATH MOVWF HIGHTEMPLATE MOVF BYTE,W XORWF HIGHTEMPLATE, F ; APPLY INPUT OVER MASK ;******************************* ; ; LOWTEMPLATE AND HIGHTEMPLATE ; CONTAIN THE EXPECTED VALUES ; FOR THE INCOMING BIT ; ;******************************* MOVLW LOW A697SIN MOVWF FSR ;ACCUMULATOR ADDR MOVLW 8 MOVWF SAMPLEBIT COMPAREBITL RLF LOWTEMPLATE,F BTFSS STATUS,C GOTO MATCHL DECF INDF,F GOTO CONTINL MATCHL INCF INDF,F CONTINL INCF FSR,F DECFSZ SAMPLEBIT,F GOTO COMPAREBITL ;FINISH THE BYTE MOVLW LOW A1209SIN MOVWF FSR ;ACCUMULATOR ADDR MOVLW 8 MOVWF SAMPLEBIT COMPAREBITH RLF HIGHTEMPLATE,F BTFSS STATUS,C GOTO MATCHH DECF INDF,F GOTO CONTINH MATCHH INCF INDF,F CONTINH INCF FSR,F DECFSZ SAMPLEBIT,F GOTO COMPAREBITH ;FINISH THE BYTE ;******************************** ; ; Increment Tablecounter 0..255 ; ;******************************** INCF TABLECOUNTER,F MOVF TABLECOUNTER,W XORLW D'255' ;This is the number of samples to test against (max 7f) BTFSS STATUS,Z GOTO C_RESTORE BSF DONE ; DTMF DECISION ALGORITHM ; compute absolute value acc = ABS(acc) MOVLW H'30' MOVWF FSR TESTFORNEG BTFSC INDF,7 GOTO NEG GOTO NEXT NEG ; SUBTRACT F FROM 0 MOVF INDF,W SUBLW 0 MOVWF INDF NEXT INCF FSR,F MOVF FSR,W XORLW H'40' BTFSS STATUS,Z GOTO TESTFORNEG ; add acumulator results for sin and cos MOVLW H'30' MOVWF FSR MORERESULTS MOVF INDF,W CLRF INDF INCF FSR,F ADDWF INDF,F MOVF FSR,W INCF FSR,F XORLW H'3F' BTFSS STATUS,Z GOTO MORERESULTS ; compare acc with 64 of 255 MOVLW 0X31 MOVWF FSR TEMPX1 MOVF INDF,W SUBLW D'64' ;THRESHOLD RRF RESULT,F INCF FSR,F INCF FSR,F MOVF FSR,W XORLW 0X41 BTFSS STATUS,Z GOTO TEMPX1 COMF RESULT,F ; RESULT IS 1633/1477/1336/1209/941/852/770/697 FOR VALUE>64 ; DECISION ALGORITHM : A VALUE MUST BE DETECTED AT LEAST 2-3 TIMES ; BEFORE IS CONSIDERED VALID / MOVF RESULT, W XORWF TEMP_VAL,W ; COMPARE RESULT WITH TEMP_VAL BTFSC STATUS, Z GOTO DECI1 ; == CLRF TEMP_TIMES MOVF RESULT,W ; TEMP_TIMES = 0 MOVWF TEMP_VAL ; TEMP_VAL = RESULT GOTO CLEANUP ; START AGAIN DECI1 MOVLW 0XFF XORWF TEMP_TIMES,W ; COMPARE TEMP_TIMES/255 BTFSC STATUS,Z GOTO CLEANUP ; ==255, START AGAIN INCF TEMP_TIMES, F ; <> 255, INC TEMP_TIMES DECI3 MOVLW .1 ; 2 TIMES DETECTED -1 XORWF TEMP_TIMES,W BTFSS STATUS,Z GOTO CLEANUP ; <> START AGAIN ; GOT ONE VALUE 2 TIMES !!!!!!!!!!! CLRW XORWF TEMP_VAL, W ; COMPARE TEMP_VAL / 0 BTFSC STATUS,Z GOTO CLEANUP ; ==0, START AGAIN DECI2 ; <>0 ;********************************************** ; GOT ONE CHARACTER, CONVERT IT TO ASCII.... ;********************************************** MOVF RESULT,W XORLW D'17' BTFSC STATUS,Z GOTO GOTCHA1 MOVF RESULT,W XORLW D'33' BTFSC STATUS,Z GOTO GOTCHA2 MOVF RESULT,W XORLW D'65' BTFSC STATUS,Z GOTO GOTCHA3 MOVF RESULT,W XORLW D'18' BTFSC STATUS,Z GOTO GOTCHA4 MOVF RESULT,W XORLW D'34' BTFSC STATUS,Z GOTO GOTCHA5 MOVF RESULT,W XORLW D'66' BTFSC STATUS,Z GOTO GOTCHA6 MOVF RESULT,W XORLW D'20' BTFSC STATUS,Z GOTO GOTCHA7 MOVF RESULT,W XORLW D'36' BTFSC STATUS,Z GOTO GOTCHA8 MOVF RESULT,W XORLW D'68' BTFSC STATUS,Z GOTO GOTCHA9 MOVF RESULT,W XORLW D'40' BTFSC STATUS,Z GOTO GOTCHA0 MOVF RESULT,W XORLW D'72' BTFSC STATUS,Z GOTO GOTCHAPOUND MOVF RESULT,W XORLW D'24' BTFSC STATUS,Z GOTO GOTCHASTAR ; GOT ONLY TRASH... CLRF TEMP_TIMES GOTO CLEANUP ; CONVERT ASCII GOTCHAPOUND MOVLW H'23' GOTO SENDIT GOTCHASTAR MOVLW H'2A' GOTO SENDIT GOTCHA1 MOVLW H'31' GOTO SENDIT GOTCHA2 MOVLW H'32' GOTO SENDIT GOTCHA3 MOVLW H'33' GOTO SENDIT GOTCHA4 MOVLW H'34' GOTO SENDIT GOTCHA5 MOVLW H'35' GOTO SENDIT GOTCHA6 MOVLW H'36' GOTO SENDIT GOTCHA7 MOVLW H'37' GOTO SENDIT GOTCHA8 MOVLW H'38' GOTO SENDIT GOTCHA9 MOVLW H'39' GOTO SENDIT GOTCHA0 MOVLW H'30' GOTO SENDIT SENDIT MOVWF RESULT1 ; PLACE RECEIVED CHAR IN RESULT1 GOTO C_RESTORE CLEANUP MOVLW 0X2F ; start -1 MOVWF FSR TEMPXX INCF FSR,F CLRF INDF MOVF FSR,W XORLW 0X3F ; CLEAR RAM FROM 0X30-0X3F BTFSS STATUS,Z GOTO TEMPXX ; table read pointer CLRF TABLECOUNTER BCF DONE ; CLEAR DONE, START ;******************************** ; ; Context Restore ; ;******************************** C_RESTORE CLRF STATUS ;ENSURE BANK0 RESTORE MOVF FSR_SAVE,W MOVWF FSR MOVF PCLATH_SAVE,W MOVWF PCLATH ; RESTORE PCLATH SWAPF STATUS_TEMP,W MOVWF STATUS SWAPF W_TEMP,F SWAPF W_TEMP,W RETFIE ;********************************************************** ; Main Program ;********************************************************** START call init_disp call cur_h1 STARTPLUS ; INIT PORTB OUTPUTS FROM EEPROM MOVLW LOW OUT0 CALL EE_READ_BYTE ANDLW 0X0F ; MASK THE LOW 4 BITS MOVWF PORTB ; SET OUTPUTS Bank1 MOVLW 0XF0 MOVWF TRISB ; PORT B 0-3 OUTPUTS Bank0 BCF TIMEOUT ; KEEP THE TIMEOUT STOPPED BCF BEEP ; SILENCE... CLRF TIME0 ; INIT TIMEOUT COUNTER CLRF TIME1 CLRF TIME2 BSF DONE ; DO NOT START DTMF DETECTOR.... ; INIT ROUTINE INIT clrf PORTC ; CLEAR PORTC movlw B'11110011' ;port C0=Input for now/out, C1=INPUT, C2,3 OUT BANKSEL TRISC movwf TRISC BANKSEL T2CON MOVLW B'00001100' ; X,1/2 postscale, timer 2 ON ~9.6khz sample rate MOVWF T2CON BANKSEL PR2 MOVLW 0XFF ; TIMER 2 PERIOD REGISTER MOVWF PR2 BANKSEL PIR1 BCF PIR1,TMR2IF ; CLEAR TIMER 2 INT FLAG BANKSEL PIE1 BSF PIE1,TMR2IE ; START INT FOR TIMER 2 BANKSEL INTCON BSF INTCON,PEIE ; START PERIPHERAL INT BSF INTCON,GIE ; START GLOBAL INT BANKSEL CCP1CON MOVLW B'00001100' MOVWF CCP1CON ;PWM 1 ON BANKSEL TRISC BCF TRISC,2 ; RC2 = PWM 1 OUT BANKSEL CCPR1L MOVLW .128 MOVWF CCPR1L ; 50 DUTY CYCLE ~18KHZ CLRF TEMP_VAL CLRF TEMP_TIMES CLRF COUNT ; NR CHAR FOR DISPLAY CALL TESTPASS ; PRINT PASS ; TO STOP DTMF DETECTOR - BSF DONE ; TO START DTMF DETECTOR - CALL START_DTMF CALL BEEPOK CALL BEEPERR ;********************************* ; MAIN LOOP ;********************************* ; FIRSRT READ #PASS#, WHERE PASS HAS 10 DIGITS MAINDTMF: CALL START_DTMF CALL CLRTIMEOUT MAIN0: BTFSC TIMEOUT GOTO TIMEO1 ; TIMEOUT ERROR, NO SOUND, HANG UP LINE ; FIRST WAIT A DIGIT BTFSS DONE GOTO MAIN0 ; WE GOT A DIGIT, COMPARE WITH # MOVLW '#' ; WAIT # XORWF RESULT1,W BTFSS STATUS,Z GOTO MAINDTMF ; DIGIT<>#, TRY AGAIN ; debug call cur_h1 movf RESULT1,w call send_c ; end debug BSF PORTC,3 ; BEEP ON CALL START_DTMF ; GET A NEW DIGIT CALL CLRTIMEOUT ; START TIMEUOT MOVLW LOW PSS0 ; POINTER RAM MOVWF FSR MOVLW .10 ; 10 DIGIT PASS MOVWF EE_Byte ; COUNTER MAIN1: BTFSC TIMEOUT GOTO TIMEO ; TIMEOUT ERROR, RESTART ; WAIT A DIGIT BTFSS DONE GOTO MAIN1 MOVF RESULT1,W MOVWF INDF ; PUT DIGIT IN PSS0-9, RAM ;debug call send_c ;end debug DECF EE_Byte,F BTFSC STATUS,Z GOTO MAIN21 ; GOT 10 DIGITS INCF FSR,F CALL START_DTMF CALL CLRTIMEOUT GOTO MAIN1 ; WAIT FOR DIGIT 1..9 MAIN21: CALL START_DTMF CALL CLRTIMEOUT MAIN2: ; WAIT # BTFSC TIMEOUT GOTO TIMEO ; TIMEOUT ERROR, RESTART ; WAIT A DIGIT BTFSS DONE GOTO MAIN2 MOVLW '#' ; COMPARE # XORWF RESULT1,W BTFSS STATUS,Z GOTO MAINDTMF ; DIGIT<>#, RESTART ;debug movf RESULT1,w call send_c ;end debug ; COMPARE PASSWORD MOVLW LOW PASS0 MOVWF EE_Byte ; EE_BYTE POINER EEPROM MOVLW LOW PSS0 MOVWF FSR ; FSR POINER RAM MOVLW .10 MOVWF scrA ; SCRA COUNTER MAIN5: MOVF EE_Byte,W ; W= EEPROM DIGIT CALL EE_READ_BYTE XORWF INDF,W BTFSC STATUS,Z GOTO MAIN3 ; PASS BAD CALL BEEPERR GOTO MAINDTMF ; RESTART, PASSWORD BAD MAIN3: DECF scrA,F BTFSC STATUS,Z GOTO MAIN4 ; PASS OK, CONTINUE INCF EE_Byte,F ; NEXT DIGIT INCF FSR,F GOTO MAIN5 MAIN4: ;CALL BEEPOK ; PASS OK ; READ 3 DIGITS IN PSS 0,1,2 CALL START_DTMF ; GET A NEW DIGIT CALL CLRTIMEOUT ; START TIMEUOT MOVLW LOW PSS0 ; POINTER RAM MOVWF FSR MOVLW .3 ; READ ONLY 3 DIGITS MOVWF EE_Byte ; COUNTER MAIN6: BTFSC TIMEOUT GOTO TIMEO ; TIMEOUT ERROR, RESTART ; WAIT A DIGIT BTFSS DONE GOTO MAIN6 MOVF RESULT1,W MOVWF INDF ; PUT DIGIT IN PSS0-9, RAM ;debug call send_c ;end debug DECF EE_Byte,F BTFSC STATUS,Z GOTO MAIN7 ; GOT 10 DIGITS INCF FSR,F CALL START_DTMF CALL CLRTIMEOUT GOTO MAIN6 ; WAIT FOR DIGIT 1..9 MAIN7: ; GOT 3 DIGITS ; IF PSS 1,2 = ## THEN #PASS#1-4## = VERIFY MOVLW '#' XORWF PSS1,W BTFSS STATUS,Z GOTO NOVERIFY MOVLW '#' XORWF PSS2,W BTFSS STATUS,Z GOTO NOVERIFY VERIFY: ; VERIFY COMMAND ;********************************************************************** ; CHECK PSS0 FOR 1-4 --> 31,32,33,34 MOVLW '1' XORWF PSS0,W BTFSC STATUS,Z GOTO VERIFY1 MOVLW '2' XORWF PSS0,W BTFSC STATUS,Z GOTO VERIFY1 MOVLW '3' XORWF PSS0,W BTFSC STATUS,Z GOTO VERIFY1 MOVLW '4' XORWF PSS0,W BTFSC STATUS,Z GOTO VERIFY1 GOTO TIMEO VERIFY1: ; EXECUTE VERIFY COMMAND MOVLW .1 MOVWF PSS1 ; PSS1 TEMP MOVLW '0' SUBWF PSS0, F ;SUBSTRACT PSS0-W = 0-3 VERIFY2: DECF PSS0, F BTFSC STATUS,Z GOTO VERIFY3 ; READY BCF STATUS,C RLF PSS1,F GOTO VERIFY2 VERIFY3: MOVLW LOW OUT0 CALL EE_READ_BYTE ; RETRIEVE VALUES FROM EEPROM ANDWF PSS1,W ; AND MASK BTFSC STATUS,Z GOTO VERIFYOFF VERIFYON: CALL BEEPOK ; OUTPUT = 1 GOTO MAINDTMF VERIFYOFF: CALL BEEPERR GOTO MAINDTMF NOVERIFY: ; GET PSS3,4 CALL START_DTMF ; GET A NEW DIGIT CALL CLRTIMEOUT ; START TIMEUOT MOVLW LOW PSS3 ; POINTER RAM MOVWF FSR MOVLW .2 ; READ ONLY 2 DIGITS MOVWF EE_Byte ; COUNTER MAIN8: BTFSC TIMEOUT GOTO TIMEO ; TIMEOUT ERROR, RESTART ; WAIT A DIGIT BTFSS DONE GOTO MAIN8 MOVF RESULT1,W MOVWF INDF ; PUT DIGIT IN PSS0-9, RAM ;debug call send_c ;end debug DECF EE_Byte,F BTFSC STATUS,Z GOTO MAIN9 ; GOT 10 DIGITS INCF FSR,F CALL START_DTMF CALL CLRTIMEOUT GOTO MAIN8 ; WAIT FOR DIGIT 1..9 MAIN9: ; GOT PSS3,4 ; IF PSS 3,4 = ## THEN #PASS#1-4#0-1## = SET MOVLW '#' XORWF PSS3,W BTFSS STATUS,Z GOTO NOSET MOVLW '#' XORWF PSS4,W BTFSS STATUS,Z GOTO NOSET XSET: ; SET COMMAND ;********************************************************************** ; CHECK PSS1 FOR # MOVLW '#' XORWF PSS1,W BTFSS STATUS,Z GOTO TIMEO ; CHECK PSS0 FOR 1-4 --> 31,32,33,34 MOVLW '1' XORWF PSS0,W BTFSC STATUS,Z GOTO XSET1 MOVLW '2' XORWF PSS0,W BTFSC STATUS,Z GOTO XSET1 MOVLW '3' XORWF PSS0,W BTFSC STATUS,Z GOTO XSET1 MOVLW '4' XORWF PSS0,W BTFSC STATUS,Z GOTO XSET1 GOTO TIMEO XSET1: ; CHECK PSS2 FOR 0-1 --> 30,31 MOVLW '0' XORWF PSS2,W BTFSC STATUS,Z GOTO XSET2 MOVLW '1' XORWF PSS2,W BTFSC STATUS,Z GOTO XSET2 GOTO TIMEO XSET2: ; EXECUTE SET COMMAND MOVLW .1 MOVWF PSS1 ; PSS1 TEMP MOVLW '0' SUBWF PSS0, F ;SUBSTRACT PSS0-W = 0-3 SET2: DECF PSS0, F BTFSC STATUS,Z GOTO SET1 ; READY BCF STATUS,C RLF PSS1,F GOTO SET2 SET1: ; PSS1 HAS THE DESIERED BIT SET MOVLW '0' SUBWF PSS2, F ;SUBSTRACT PSS2-W = 0-1 BTFSC STATUS,Z GOTO SETRESET SETSET: MOVLW LOW OUT0 CALL EE_READ_BYTE ; RETRIEVE VALUES FROM EEPROM IORWF PSS1,W ; OR MASK MOVWF PORTB ; OUTPUT THE NEW VALUE MOVWF EE_Byte MOVLW LOW OUT0 CALL EE_WRITE_BYTE ; WRITE THE NEW VALUE TO EEPROM CALL BEEPOK ; BEEP HAPPY... GOTO MAINDTMF ; RESTART SETRESET: COMF PSS1,F ; COMPLEMENT MASK MOVLW LOW OUT0 CALL EE_READ_BYTE ; RETRIEVE VALUES FROM EEPROM ANDWF PSS1,W ; OR MASK MOVWF PORTB ; OUTPUT THE NEW VALUE MOVWF EE_Byte MOVLW LOW OUT0 CALL EE_WRITE_BYTE ; WRITE THE NEW VALUE TO EEPROM CALL BEEPOK ; BEEP HAPPY... GOTO MAINDTMF ; RESTART NOSET: ; CHECK FOR PASS CHANGE ; GET PSS5,10 CALL START_DTMF ; GET A NEW DIGIT CALL CLRTIMEOUT ; START TIMEUOT MOVLW LOW PSS5 ; POINTER RAM MOVWF FSR MOVLW .5 ; READ ONLY 5 DIGITS MOVWF EE_Byte ; COUNTER MAIN10: BTFSC TIMEOUT GOTO TIMEO ; TIMEOUT ERROR, RESTART ; WAIT A DIGIT BTFSS DONE GOTO MAIN10 MOVF RESULT1,W MOVWF INDF ; PUT DIGIT IN PSS0-9, RAM ;debug call send_c ;end debug DECF EE_Byte,F BTFSC STATUS,Z GOTO MAIN11 ; GOT 10 DIGITS INCF FSR,F CALL START_DTMF CALL CLRTIMEOUT GOTO MAIN10 ; WAIT FOR DIGIT 1..9 MAIN11: ; WAIT FOR # CALL START_DTMF CALL CLRTIMEOUT MAIN12: ; WAIT # BTFSC TIMEOUT GOTO TIMEO ; TIMEOUT ERROR, RESTART ; WAIT A DIGIT BTFSS DONE GOTO MAIN12 MOVLW '#' ; COMPARE # XORWF RESULT1,W BTFSS STATUS,Z GOTO MAINDTMF ; DIGIT<>#, RESTART ; GET 10 DIGITS IN DIG_10...DIG1 CALL START_DTMF ; GET A NEW DIGIT CALL CLRTIMEOUT ; START TIMEUOT MOVLW LOW dig_10 ; POINTER RAM MOVWF FSR MOVLW .10 ; 10 DIGIT PASS MOVWF EE_Byte ; COUNTER MAIN13: BTFSC TIMEOUT GOTO TIMEO ; TIMEOUT ERROR, RESTART ; WAIT A DIGIT BTFSS DONE GOTO MAIN13 MOVF RESULT1,W MOVWF INDF ; PUT DIGIT IN DIG_10..1, RAM DECF EE_Byte,F BTFSC STATUS,Z GOTO MAIN14 ; GOT 10 DIGITS INCF FSR,F CALL START_DTMF CALL CLRTIMEOUT GOTO MAIN13 ; WAIT FOR DIGIT 1..9 MAIN14: ; WAIT FOR # CALL START_DTMF CALL CLRTIMEOUT MAIN15: ; WAIT # BTFSC TIMEOUT GOTO TIMEO ; TIMEOUT ERROR, RESTART ; WAIT A DIGIT BTFSS DONE GOTO MAIN15 MOVLW '#' ; COMPARE # XORWF RESULT1,W BTFSS STATUS,Z GOTO MAINDTMF ; DIGIT<>#, RESTART CALL START_DTMF CALL CLRTIMEOUT MAIN151: ; WAIT # BTFSC TIMEOUT GOTO TIMEO ; TIMEOUT ERROR, RESTART ; WAIT A DIGIT BTFSS DONE GOTO MAIN151 MOVLW '#' ; COMPARE # XORWF RESULT1,W BTFSS STATUS,Z GOTO MAINDTMF ; DIGIT<>#, RESTART ; COMPARE PSS0..9 WITH DIG_10..1 ; COMPARE PASSWORD MOVLW LOW dig_10 MOVWF EE_Byte ; EE_BYTE POINER DIG_10..1 MOVLW LOW PSS0 MOVWF FSR ; FSR POINER RAM PSS0..9 MOVLW .10 MOVWF scrA ; SCRA COUNTER MAIN16: MOVF FSR,W MOVWF scrB ; STORE FSB TEMP MOVF EE_Byte,W MOVWF FSR ; POINTER TO DIG MOVF INDF, W ; READ DIG MOVWF scrC ; STORE TEMP DIG MOVF scrB, W MOVWF FSR ; RESTORE POINTER FOR PSS MOVF scrC,W ; RESTORE DIG VALUE IN W XORWF INDF,W ; COMPARE DIG/PSS BTFSC STATUS,Z GOTO MAIN17 ; PASS BAD CALL BEEPERR GOTO MAINDTMF ; RESTART, PASSWORD BAD MAIN17: DECF scrA,F BTFSC STATUS,Z GOTO MAIN18 ; PASS OK, CONTINUE INCF EE_Byte,F ; NEXT DIGIT INCF FSR,F GOTO MAIN16 MAIN18: ;NEW PASS OK, WRITE NEW PASS FROM PSS0..9 TO EEPROM PASS0..9 MOVLW LOW PSS0 MOVWF FSR ; FSR POINER RAM PSS0..9 MOVLW .10 MOVWF scrA ; SCRA COUNTER MOVLW LOW PASS0 MOVWF scrB ; POINTER TO EEPROM MAIN19: MOVF INDF,W ; READ FROM RAM MOVWF EE_Byte ; TO EE_Byte MOVF scrB, W ; POINTER IN EEPROM CALL EE_WRITE_BYTE ; WRITE THE BYTE DECF scrA,F BTFSC STATUS,Z GOTO MAIN20 ; PASS OK, CONTINUE INCF scrB,F ; NEXT DIGIT INCF FSR,F GOTO MAIN19 MAIN20: ;debug call cur_h1 call TESTPASS ;end debug CALL BEEPOK ; PASS CHANGED GOTO MAINDTMF ;*************************************************************** TIMEO: ; TIMEOUT + TIMEOUT BEEP BSF DONE ;STOP DTMF DECODER CALL BEEPERR ; TIMEOUT BEEP, TWO LOW BEEPS CALL BEEPPAUSE CALL BEEPERR TIMEO1: BSF DONE ;STOP DTMF DECODER BCF PORTC,3 ; BEEP OFF GOTO MAINDTMF ;RESTART ; ****** END MAIN LOOP ;START DTMF DECODER START_DTMF BSF DONE ; STOP DTMF INT ROUTINE MOVF FSR,W MOVWF FSR_SAVE_DTMF ; SAVE FSR MOVLW 0X2F ; start -1 MOVWF FSR TEMPXX1 INCF FSR,F CLRF INDF MOVF FSR,W XORLW 0X3F ; CLEAR RAM FROM 0X30-0X3F BTFSS STATUS,Z GOTO TEMPXX1 ; table read pointer CLRF TABLECOUNTER CLRF RESULT1 ; CLEAR RESULT DIGIT MOVF FSR_SAVE_DTMF, W MOVWF FSR ; RESTORE FSR BCF DONE ; CLEAR DONE, START DTMD INT ROUTINE RETURN ; BEEP ON ERROR, DESTROY scrA! BEEPERR: MOVLW .16 GOTO BEEP1 ; BEEP WHEN OK, DESTROY scrA! BEEPOK: MOVLW .4 BEEP1: MOVWF TIME2 ; BEEP PITCH MOVWF scrA BANKSEL TRISC BCF TRISC,0 ; PORTC 0 = OUT BANKSEL PORTC ; BACK TO BANK 0 BSF BEEP ; START INT BEEP ROUTINE BSF TIMEOUT ; STOP TIMEOUT ROUTINE CLRF TIME0 ; INIT TIMEOUT COUNTER MOVLW .25 MOVWF TIME1 BCF TIMEOUT ; START TIMEOUT BEEPWAIT: BTFSS TIMEOUT GOTO BEEPWAIT BCF BEEP ; STOP INT BEEP ROUTINE BCF PORTC,0 ; SET OUTPUT TO 0 VOLTS BANKSEL TRISC BSF TRISC,0 ; PORTC 0 = INPUT / HIGH z BANKSEL PORTC ; BACK TO BANK 0 RETURN ; BEEPPAUSE WAIT A LITTLE BIT.... BEEPPAUSE: BSF TIMEOUT ; STOP TIMEOUT ROUTINE CLRF TIME0 ; INIT TIMEOUT COUNTER MOVLW .10 MOVWF TIME1 BCF TIMEOUT ; START TIMEOUT BEEPWAIT1: BTFSS TIMEOUT GOTO BEEPWAIT1 RETURN ; CLEAR TIMEOUT TIMER CLRTIMEOUT: ; CLEAR TIMEOUT TIMER ( ~6.7 SECONDS) BCF TIMEOUT ; STOP INT TIMEOUT ROUTINE CLRF TIME0 ; INIT TIMEOUT COUNTER CLRF TIME1 BCF TIMEOUT ; START INT TIMEOUT ROUTINE RETURN ; PRINT PASSWORD IN EEPROM TESTPASS: MOVLW .8 MOVWF EE_Byte TESTPASS1: MOVF EE_Byte,W CALL EE_READ_BYTE CALL send_c ; PRINT DIGIT INCF EE_Byte,F MOVLW 0X12 ; END OF PASS+1 XORWF EE_Byte, W BTFSS STATUS, Z GOTO TESTPASS1 CALL cur_h1 RETURN ;********************** ; UTILITY ROUTINES ;********************** ; ; 8/15/02 ; ; display routines, 16F87X Q=20Mhz ; display IC HD44780A00 / 16X2 ; Display connected to Port D ; ; PORTD0 DATA4 ; PORTD1 DATA5 ; PORTD2 DATA6 ; PORTD3 DATA7 ; DATA0-3 - GROUND ; PORTD4 RS ; PORTD5 E ; PORTD6 - NOT USED ; PORTD7 - NOT USED ; ; ; ; init_disp - initialize display ; cur_h1 - cursor home line 1 ; cur_h2 - cursor home line 2 ; ; movlw LOW text ; movwf comA ; movlw HIGH text ; movwf comB ; call prt_rom - print the text in Rom (comB:comA) ; ; binbcdU8 - convert 8 bit unsigned count_1 to dis_2,dis_1 ; bcdascii8 - Convert bcd dis_2..1 in ASCII dis_4..1 ; leadzero8 - delete leading zeroes from dig_4 - dig_2 ; dispU8 - display 8 bit unsigned count_1 to dis_4..1, +1 stack level ; dispS8 - display 8 bit signed count_1 to dis_4..1, +1 stack level ; binbcdU32 - convert 32 bit unsigned count_4:3:2:1-->dig_5..1, 10 digits, dis_5 low nibble=MSD, +1 stack level ; bcdascii32 - Convert bcd dig_5..1 in ASCII dig_9..1 ; leadzero32 - delete leading zeroes from dig_10 - dig_2 ; prtram - print from RAM, string located at (IRP:W) ; send_c - send char in W ; send caracter in W + 100 uS delay send_c: movwf comC swapf comC, W andlw 0xF iorlw 0x10 ;RS=1 movwf PORTD ;E=0 nop bsf PORTD,0x5;E=1 nop nop bcf PORTD,0x5;E=0 goto $+1 goto $+1 ;delay 1 uS movf comC, W andlw 0xF iorlw 0x10 ;RS=1 movwf PORTD ;E=0 nop bsf PORTD,0x5;E=1 nop nop bcf PORTD,0x5;E=0 ; delay 100 uS del_100: movlw 165 ; 165 = 100uS movwf scrA del_100A: decfsz scrA, F goto del_100A return ; send byte in W send_b: movwf comC swapf comC, W ; high nibble andlw 0xF movwf PORTD ;E=0 nop bsf PORTD,0x5;E=1 nop nop bcf PORTD,0x5;E=0 goto $+1 goto $+1 ; delay 1uS movf comC, W ; Low nibble andlw 0xF movwf PORTD ; E=0 nop bsf PORTD,0x5; E=1 nop nop bcf PORTD,0x5; E=0 return ; send nibble, low w send_n: movwf PORTD ; E=0 nop bsf PORTD,0x5 ; E=1 nop nop bcf PORTD,0x5 ; E=0 return ; print the string located at (comB:comA) in program memory prt_rom: Bank2 prt_rom1: movf comA, W ;Write the movwf EEADR ;address bytes movf comB, W movwf EEADRH bsf STATUS, RP0 ;Bank3 bsf EECON1, EEPGD ;Point to program memory bsf EECON1, RD ;start read operation nop ;required two nop's nop bcf STATUS, RP0 ;Bank2 movf EEDATA, W ;char in W andlw 0xFF ;compare 0 btfsc STATUS, Z goto prt_rom2 Bank0 call send_c ; print char in w+100uS wait incfsz comA, F goto prt_rom incf comB, F goto prt_rom prt_rom2: Bank0 return ; cursor home line 1 cur_h1: movlw 0x80 cur_h11: call send_b call del_100 return ; cursor home line 2 cur_h2: movlw 0xC0 goto cur_h11 ; delay 1 ms del_1m: movlw 0xA ; w=delayX100nS del_1mx: movwf scrB del_1mA: decfsz scrB, F goto del_1mB return del_1mB: movlw 165 movwf scrA del_1mC: decfsz scrA, F goto del_1mC goto del_1mA prt_ram: ;print from RAM, string located at (IRP:W) movwf FSR prt_ram1: movlw 0 subwf INDF, w ; compare 0 btfsc STATUS, Z return ; char = zero movf INDF, W call send_c incf FSR, F goto prt_ram1 leadzero8: ; delete leading zeroes from dig_4 - dig_2 BCF STATUS, IRP movlw .3 movwf scrA movlw LOW dig_4 goto leadzeroin leadzero32: ; delete leading zeroes from dig_10 - dig_2 BCF STATUS, IRP movlw .9 movwf scrA movlw LOW dig_10 leadzeroin: movwf FSR leadz1: movlw 0x30 ; ascii zero subwf INDF, w ; compare 0x30 btfss STATUS, Z return ; first char <>zero movlw 0x20 ; ascii space movwf INDF decf scrA, F btfsc STATUS, Z ; exit if zero return incf FSR, F goto leadz1 bcdascii32: ; Convert bcd dis_5..1 in ASCII dis_9..1 swapf dig_5, W andlw 0x0F addlw 0x30 movwf dig_10 movf dig_5, W andlw 0x0F addlw 0x30 movwf dig_9 swapf dig_4, W andlw 0x0F addlw 0x30 movwf dig_8 movf dig_4, W andlw 0x0F addlw 0x30 movwf dig_7 swapf dig_3, W andlw 0x0F addlw 0x30 movwf dig_6 movf dig_3, W andlw 0x0F addlw 0x30 movwf dig_5 bcdascii8: ; Convert bcd dis_2..1 in ASCII dis_4..1 swapf dig_2, W andlw 0x0F addlw 0x30 movwf dig_4 movf dig_2, W andlw 0x0F addlw 0x30 movwf dig_3 swapf dig_1, W andlw 0x0F addlw 0x30 movwf dig_2 movf dig_1, W andlw 0x0F addlw 0x30 movwf dig_1 return dispS8: ; display 8 bit signed count_1 to dis_4..1, +1 stack level btfss count_1,7 goto dispU8 ; disp neg 8 comf count_1, F ; complement incf count_1, F ; X(-1) call binbcdU8 ; dis2..1 bcd call bcdascii8 ; dis4..1 ascii ; leadzero and - delete leading zeroes from dig_4..2 and add the - sign BCF STATUS, IRP movlw .4 movwf scrA movlw LOW dig_4 movwf FSR leadzN1: movlw 0x30 ; ascii zero subwf INDF, w ; compare 0x30 btfss STATUS, Z goto leadzN2 ; first char <>zero, add - movlw 0x20 ; ascii space movwf INDF decf scrA, F btfsc STATUS, Z ; exit if zero return incf FSR, F goto leadzN1 leadzN2: ; dec pointer and display "-" decf FSR, F movlw "-" ; ascii - movwf INDF return return dispU8: ; display 8 bit unsigned count_1 to dis_4..1, +1 stack level call binbcdU8 call bcdascii8 call leadzero8 return binbcdU8: ; convert 8 bit unsigned count_1 to dis_2,dis_1 bcf STATUS,C ; clear the carry bit BCF STATUS, IRP ;Page zero or 1 for indirect movlw 8 movwf scrA clrf dig_1 clrf dig_2 loop8: rlf count_1,F rlf dig_1, F rlf dig_2, F ; decfsz scrA, F goto adjDEC8 RETLW 0 ; adjDEC8: movlw dig_1 movwf FSR movlw 0x3 addwf INDF,W movwf scrB btfsc scrB,3 ; test if result > 7 movwf INDF movlw 0x30 addwf INDF,W movwf scrB btfsc scrB,7 ; test if result > 7 movwf INDF ; save as MSD ; movlw dig_2 movwf FSR movlw 0x3 addwf INDF,W movwf scrB btfsc scrB,3 ; test if result > 7 movwf INDF movlw 0x30 addwf INDF,W movwf scrB btfsc scrB,7 ; test if result > 7 movwf INDF ; save as MSD goto loop8 ; binbcdU32: ; convert 32 bit unsigned count_4:3:2:1-->dig_5..1, 10 digits, ; dis_5 low nibble=MSD, +1 stack level bcf STATUS,C ; clear the carry bit BCF STATUS, IRP ;Page zero or 1 for indirect movlw 32 movwf scrA clrf dig_1 clrf dig_2 clrf dig_3 clrf dig_4 clrf dig_5 loop28: rlf count_1,F rlf count_2,F rlf count_3,F rlf count_4,F rlf dig_1, F rlf dig_2, F rlf dig_3, F rlf dig_4, F rlf dig_5, F ; decfsz scrA, F goto adjDEC RETLW 0 ; adjDEC: movlw dig_1 movwf FSR call adjBCD ; movlw dig_2 movwf FSR call adjBCD ; movlw dig_3 movwf FSR call adjBCD ; movlw dig_4 movwf FSR call adjBCD ; movlw dig_5 movwf FSR call adjBCD goto loop28 adjBCD: movlw 0x3 addwf INDF,W movwf scrB btfsc scrB,3 ; test if result > 7 movwf INDF movlw 0x30 addwf INDF,W movwf scrB btfsc scrB,7 ; test if result > 7 movwf INDF ; save as MSD RETLW 0 ; init display in 4 bit transfer mode init_disp: Bank0 clrf PORTD Bank1 movlw B'11000000' ; port D<0..5>=out movwf TRISD Bank0 movlw 200 ; 20ms call del_1mx movlw 0x3 call send_n movlw 50 ; 5ms call del_1mx movlw 0x3 call send_n call del_100 ; 100uS movlw 0x3 call send_n call del_100 movlw 0x2 call send_n call del_1m movlw 0x28 ; function, 4 bit data, 2 line, 5X7 call send_b call del_1m movlw 0x6 ; Entry mode set, increment, no shift call send_b call del_100 movlw 0xE ; display on, cursor on, blink off call send_b call del_100 movlw 0x1 ; display clear call send_b movlw 30 ; 2 ms delay to clear the display call del_1mx return linie1: DE "Display Test X",0 ;**************************** ;EEprom routines by Tony Kubek DISABLE_IRQ MACRO LOCAL STOP_INT STOP_INT BCF INTCON,GIE ; disable global interrupt BTFSC INTCON,GIE ; check if disabled GOTO STOP_INT ; nope, try again ENDM ;+++++ ; ENABLE_IRQ enable global irq ENABLE_IRQ MACRO BSF INTCON,GIE ; enable global interrupt ENDM ; *********************************************************************** ; EE_WRITE_BYTE - Routine to write a byte to ee ram ; Adress in W, byte MUST be in EE_Byte EE_WRITE_BYTE Bank2 ; select bank2 MOVWF EEADR ; setup adress Bank0 ; MOVF EE_Byte,W ; get byte Bank2 MOVWF EEDATA ; setup byte to write BSF STATUS,RP0 ; bank3 !! BCF EECON1,EEPGD ; set to data ee ram BSF EECON1,WREN ; enable writes DISABLE_IRQ ; disable irq's MOVLW H'55' ; required sequence !! MOVWF EECON2 MOVLW H'AA' MOVWF EECON2 BSF EECON1,WR ; begin write procedure ENABLE_IRQ ; enable irq's again BCF EECON1,WREN ; disable writes ( does not affect current write cycle ) Bank0 ; reset to bank0 ; wait for the write to complete before we return BTFSS PIR2,EEIF ; wait for interrupt flag to be set GOTO $-1 ; clear interupt bit and write enable bit BCF PIR2,EEIF ;clear eewrite irq flag RETURN ; *********************************************************************** ; EE_READ_BYTE - Routine to read a byte from ee ram ; Adress in W, byte will be delivered in W EE_READ_BYTE Bank2 MOVWF EEADR ; put in adress reg. BSF STATUS,RP0 ; bank3 !! BCF EECON1,EEPGD ; set to read data memory BSF EECON1,RD ; set bit to read BCF STATUS,RP0 ; bank2 !! MOVF EEDATA,W ; move data to W Bank0 ; Reset to BANK0 ! RETURN ; and return ;*************************************************************************** org 0x0600 ; page 0 LOWBAND ADDWF PCL,F RETLW B'11111111' RETLW B'11111111' RETLW B'11111010' RETLW B'10101010' RETLW B'10101010' RETLW B'10100000' RETLW B'10000000' RETLW B'00000001' RETLW B'00000101' RETLW B'00010101' RETLW B'01010111' RETLW B'01011111' RETLW B'01111110' RETLW B'01111110' RETLW B'11111010' RETLW B'11101000' RETLW B'11101000' RETLW B'10100000' RETLW B'10100001' RETLW B'10000001' RETLW B'10000111' RETLW B'00000111' RETLW B'00011111' RETLW B'00011110' RETLW B'01011110' RETLW B'01111000' RETLW B'01111000' RETLW B'01111000' RETLW B'11100001' RETLW B'11100001' RETLW B'11100001' RETLW B'10000111' RETLW B'10000111' RETLW B'10000110' RETLW B'10011110' RETLW B'00011110' RETLW B'00011100' RETLW B'00011000' RETLW B'01111001' RETLW B'01111001' RETLW B'01110001' RETLW B'01100011' RETLW B'11100111' RETLW B'11100111' RETLW B'11000110' RETLW B'10001110' RETLW B'10001100' RETLW B'10011100' RETLW B'10011000' RETLW B'00011001' RETLW B'00111001' RETLW B'00110011' RETLW B'01110011' RETLW B'01100011' RETLW B'01100110' RETLW B'01100110' RETLW B'11100110' RETLW B'11001100' RETLW B'11001100' RETLW B'10001101' RETLW B'10011001' RETLW B'10011001' RETLW B'10011011' RETLW B'00110011' RETLW B'00110010' RETLW B'00110110' RETLW B'01100110' RETLW B'01100100' RETLW B'01101100' RETLW B'01001100' RETLW B'11001101' RETLW B'11001001' RETLW B'11011011' RETLW B'10011011' RETLW B'10010011' RETLW B'10010010' RETLW B'10110010' RETLW B'00110100' RETLW B'00110100' RETLW B'00100100' RETLW B'01101101' RETLW B'01101101' RETLW B'01001101' RETLW B'01001011' RETLW B'11001011' RETLW B'11010010' RETLW B'11010010' RETLW B'10010010' RETLW B'10110100' RETLW B'10110100' RETLW B'10110101' RETLW B'00101101' RETLW B'00101101' RETLW B'00101111' RETLW B'01101011' RETLW B'01001010' RETLW B'01001010' RETLW B'01000010' RETLW B'11010000' RETLW B'11010000' RETLW B'11010100' RETLW B'10110101' RETLW B'10110101' RETLW B'10111111' RETLW B'10101111' RETLW B'00101111' RETLW B'00101010' RETLW B'00001010' RETLW B'01000000' RETLW B'01000000' RETLW B'01010000' RETLW B'01010101' RETLW B'11010101' RETLW B'11010101' RETLW B'11111111' RETLW B'10111111' RETLW B'10111110' RETLW B'10101010' RETLW B'10101010' RETLW B'00101000' RETLW B'00000000' RETLW B'00000001' RETLW B'01000001' RETLW B'01010101' RETLW B'01010111' RETLW B'01010111' RETLW B'11111111' RETLW B'11111110' RETLW B'11111010' RETLW B'10101000' RETLW B'10101000' RETLW B'10100000' RETLW B'10100001' RETLW B'00000001' RETLW B'00000111' RETLW B'00000111' RETLW B'01010111' RETLW B'01011110' RETLW B'01011110' RETLW B'01111110' RETLW B'11111000' RETLW B'11111000' RETLW B'11101001' RETLW B'10100001' RETLW B'10100001' RETLW B'10000011' RETLW B'10000111' RETLW B'00000110' RETLW B'00000110' RETLW B'00011110' RETLW B'01011100' RETLW B'01011000' RETLW B'01111000' RETLW B'01111001' RETLW B'11110001' RETLW B'11100011' RETLW B'11100011' RETLW B'10100111' RETLW B'10000110' RETLW B'10000110' RETLW B'10001100' RETLW B'00011100' RETLW B'00011100' RETLW B'00011001' RETLW B'01111001' RETLW B'01111001' RETLW B'01110011' RETLW B'01110011' RETLW B'11100010' RETLW B'11100110' RETLW B'11100110' RETLW B'10001100' RETLW B'10001100' RETLW B'10001101' RETLW B'10011001' RETLW B'00011001' RETLW B'00011011' RETLW B'00110011' RETLW B'01110011' RETLW B'01110010' RETLW B'01100110' RETLW B'01100100' RETLW B'11100100' RETLW B'11001100' RETLW B'11001101' RETLW B'10001101' RETLW B'10001011' RETLW B'10011011' RETLW B'10011011' RETLW B'00010010' RETLW B'00110010' RETLW B'00110100' RETLW B'01110100' RETLW B'01100100' RETLW B'01101101' RETLW B'01101101' RETLW B'11001101' RETLW B'11001011' RETLW B'11001011' RETLW B'10011010' RETLW B'10010010' RETLW B'10010010' RETLW B'10110000' RETLW B'00110100' RETLW B'00110101' RETLW B'00110101' RETLW B'01101101' RETLW B'01101111' RETLW B'01101111' RETLW B'01001011' RETLW B'11001010' RETLW B'11001010' RETLW B'11010000' RETLW B'10010000' RETLW B'10010100' RETLW B'10110101' RETLW B'10110101' RETLW B'00111111' RETLW B'00101111' RETLW B'00101111' RETLW B'01101010' RETLW B'01001010' RETLW B'01001010' RETLW B'01000000' RETLW B'11000000' RETLW B'11010001' RETLW B'11010101' RETLW B'10010101' RETLW B'10110111' RETLW B'10111111' RETLW B'10111110' RETLW B'00101110' RETLW B'00101010' RETLW B'00101000' RETLW B'01000000' RETLW B'01000000' RETLW B'01000001' RETLW B'01010101' RETLW B'11010111' RETLW B'11010111' RETLW B'11111111' RETLW B'10111110' RETLW B'10111110' RETLW B'10111000' RETLW B'10101000' RETLW B'00101000' RETLW B'00100001' RETLW B'00000001' RETLW B'01000001' RETLW B'01000111' RETLW B'01010111' RETLW B'01010110' RETLW B'11011110' RETLW B'11111110' RETLW B'11111100' org 0x0700 ; page 0 , avoid 256 boundary problem HIGHBAND ADDWF PCL,F RETLW B'11111111' RETLW B'11101010' RETLW B'10101000' RETLW B'10000000' RETLW B'00000101' RETLW B'00010111' RETLW B'01011111' RETLW B'01111110' RETLW B'11111000' RETLW B'11100000' RETLW B'10000001' RETLW B'10000111' RETLW B'00010111' RETLW B'00011110' RETLW B'01111000' RETLW B'01111000' RETLW B'11100001' RETLW B'11100011' RETLW B'10000111' RETLW B'10001110' RETLW B'00011100' RETLW B'00111000' RETLW B'01111001' RETLW B'01100011' RETLW B'11100111' RETLW B'11000110' RETLW B'10001100' RETLW B'10011100' RETLW B'00011001' RETLW B'00110011' RETLW B'01110011' RETLW B'01100110' RETLW B'11000100' RETLW B'11001100' RETLW B'10011001' RETLW B'10011011' RETLW B'00110011' RETLW B'00110010' RETLW B'01100100' RETLW B'01101100' RETLW B'11001101' RETLW B'11001011' RETLW B'10010011' RETLW B'10110010' RETLW B'00110100' RETLW B'00100100' RETLW B'01101101' RETLW B'01001011' RETLW B'11001011' RETLW B'11010010' RETLW B'10010000' RETLW B'10110100' RETLW B'00101101' RETLW B'00101111' RETLW B'01001011' RETLW B'01001010' RETLW B'11010000' RETLW B'11010100' RETLW B'10110101' RETLW B'10111111' RETLW B'00101111' RETLW B'00101010' RETLW B'01000000' RETLW B'01010000' RETLW B'11010101' RETLW B'11110111' RETLW B'10111111' RETLW B'10101010' RETLW B'00101000' RETLW B'00000000' RETLW B'01000001' RETLW B'01010111' RETLW B'11011111' RETLW B'11111110' RETLW B'10101000' RETLW B'10101000' RETLW B'00000001' RETLW B'00000111' RETLW B'01010111' RETLW B'01011110' RETLW B'11111000' RETLW B'11111000' RETLW B'10100001' RETLW B'10100011' RETLW B'00000111' RETLW B'00011110' RETLW B'01011100' RETLW B'01111000' RETLW B'11111001' RETLW B'11100011' RETLW B'10100111' RETLW B'10000110' RETLW B'00001100' RETLW B'00011100' RETLW B'01011001' RETLW B'01110011' RETLW B'11100011' RETLW B'11100110' RETLW B'10000100' RETLW B'10001100' RETLW B'00011001' RETLW B'00011011' RETLW B'01110011' RETLW B'01110010' RETLW B'01100100' RETLW B'11001100' RETLW B'11001101' RETLW B'10011011' RETLW B'10011011' RETLW B'00110010' RETLW B'00110100' RETLW B'01100100' RETLW B'01101101' RETLW B'11001111' RETLW B'11001011' RETLW B'10010010' RETLW B'10110000' RETLW B'00110100' RETLW B'00100101' RETLW B'01101111' RETLW B'01001011' RETLW B'11001010' RETLW B'11010000' RETLW B'10010100' RETLW B'10110101' RETLW B'00111111' RETLW B'00101111' RETLW B'01001010' RETLW B'01000000' RETLW B'11010000' RETLW B'11010101' RETLW B'10110111' RETLW B'10111111' RETLW B'00101010' RETLW B'00101000' RETLW B'01000000' RETLW B'01000001' RETLW B'11010111' RETLW B'11111111' RETLW B'10111110' RETLW B'10101000' RETLW B'00101000' RETLW B'00000001' RETLW B'01000111' RETLW B'01010111' RETLW B'11011110' RETLW B'11111100' RETLW B'10111000' RETLW B'10100001' RETLW B'00000011' RETLW B'00000110' RETLW B'01010110' RETLW B'01011100' RETLW B'11111001' RETLW B'11111001' RETLW B'10100011' RETLW B'10100010' RETLW B'00000110' RETLW B'00011100' RETLW B'01011101' RETLW B'01111001' RETLW B'11110011' RETLW B'11100010' RETLW B'10100110' RETLW B'10000100' RETLW B'00001101' RETLW B'00011001' RETLW B'01011011' RETLW B'01110010' RETLW B'11100010' RETLW B'11100100' RETLW B'10001101' RETLW B'10001101' RETLW B'00011011' RETLW B'00011010' RETLW B'01110010' RETLW B'01110100' RETLW B'11100101' RETLW B'11101101' RETLW B'10001111' RETLW B'10011010' RETLW B'00010010' RETLW B'00110000' RETLW B'01110101' RETLW B'01100101' RETLW B'11101111' RETLW B'11001010' RETLW B'10001010' RETLW B'10010000' RETLW B'00010001' RETLW B'00110101' RETLW B'01101111' RETLW B'01101110' RETLW B'11001010' RETLW B'11001000' RETLW B'10010001' RETLW B'10010101' RETLW B'00110111' RETLW B'00111110' RETLW B'01101110' RETLW B'01101000' RETLW B'11000001' RETLW B'11010001' RETLW B'10010111' RETLW B'10111110' RETLW B'00111110' RETLW B'00101000' RETLW B'01101001' RETLW B'01000001' RETLW B'01000111' RETLW B'11010110' RETLW B'11111110' RETLW B'10111100' RETLW B'10101001' RETLW B'00100001' RETLW B'00000011' RETLW B'01000110' RETLW B'01010110' RETLW B'11011100' RETLW B'11111001' RETLW B'10111001' RETLW B'10100011' RETLW B'00000010' RETLW B'00000110' RETLW B'01011100' RETLW B'01011101' RETLW B'11111001' RETLW B'11111011' RETLW B'10100010' RETLW B'10100110' RETLW B'00000100' RETLW B'00001101' RETLW B'01011101' RETLW B'01111011' RETLW B'11110010' RETLW B'11100010' RETLW B'10100100' RETLW B'10000101' RETLW B'00001101' RETLW B'00011011' RETLW B'01011010' RETLW B'01110010' RETLW B'11110100' RETLW B'11100101' RETLW B'10001101' RETLW B'10001111' RETLW B'00011010' RETLW B'00010010' RETLW B'01110000' RETLW B'01110101' RETLW B'11100101' RETLW B'11101111' RETLW B'10001010' RETLW B'10001010' RETLW B'00010000' END