; Internet Plug II ; A password protected/web enabled home appliance ; (2003) Radu Constantinescu ; constantinescuradu @yahoo.com ; Released under GNU Plublic License; ; ; ; ; list p=16f877 ; list directive to define processor #include ; processor specific variable definitions #include ; macro definitions #define debug 1 ; ; ; Outputs: ; RB0 = OUTPUT1 ; RB1 = OUTPUT2 ; RB2 = OUTPUT3 ; RB3 = OUTPUT4 ; RC0 = HeartBeat or beep ; Sequence transmitted on the serial interface: ; #PASS#1-4#0-1## SET OUTPUT on or off ; #PASS#1-4## VERIFY OUTPUT - not used ; #PASS#NEWPASS#NEWPASS## CHANGE PASS ; PASS IS 10 characters LONG ; ; turn off crossing page boundary message ERRORLEVEL -306, -302 ; base frequency XTAL_FREQ EQU 20000000 ; OSC freq in Hz #include ; serial header ;***** RAM VARIABLES DEFINITIONS ; *** Bank0 *** 80 bytes CBLOCK 0x020 Saved_Status:1 ; variable used for context saving Saved_Pclath:1 ; Saved_Fsr:1 ; ; serial buffer RX and TX pointers, buffers located in bank1 FSRSAVE:1 RX_Buffer_InPtr:1 ; where to put next incomming byte RX_Buffer_OutPtr:1 ; where to get next ( first ) byte RX_Buffer_Count:1 ; how many we have in buffer TX_Buffer_InPtr:1 ; where to put next outgoing byte TX_Buffer_OutPtr:1 ; whre to get next byte TX_Buffer_Count:1 ; how many we have in buffer TX_Temp:1 ; temporary reg used while sending Flags:1 ; flags for serial comunincation EE_Byte:1 ; Temp var for EEProm Routines Temp:1 ; temp byte ONLY to be used locally and no calls ! ; Utility routines variables 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 TIME0: 1 ;TIMEOUT COUNTER LSB TIME1: 1 ;TIMEOUT COUNTER MSB ;**************************** ; ;User Variables ; ;**************************** TIME2: 1 RESULT1: 1 ;TEMP CHAR 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 ; ************* Bit variable definitions *************************** #define _BufferOverrun Flags,0 ; Serial RX buffer overrun #define TIMEOUT Flags,1 ; timeout 3.7 sec #define BEEP Flags,2 ; beep when on #define GOT_ONE Flags,3 ; GOT_ONE is set when at least a char is in the RxBuffer #define BAD_SENT Flags,4 ; BAD PASS string sent ; *** Bank0/1/2/3 mirrored in all banks 0x70, 0xF0, 0x170, 0x1F0, 16 bytes CBLOCK 0x070 ICD_Reserved1:1 ; for icd ; ram variables accesible from all banks mainly used for context saving ; ( ram area above 0x70 are mirrored in all banks ) ;Table_Temp:1 ; table lookup temp variable ; variables for all the RAM pages Saved_W:1 ; variable used for context saving comA: 1 comB: 1 comC: 1 comD: 1 ENDC ; *** Bank1 *** 80 bytes CBLOCK 0x0A0 RX_Buffer:RX_BUFFER_SIZE ; buffer for rx TX_Buffer:TX_BUFFER_SIZE ; buffer for tx ENDC ; *** Bank2 *** extra ram 16 bytes CBLOCK 0x110 ENDC ; *** Bank2 *** 80 Bytes CBLOCK 0x120 ENDC ; *** Bank3 *** extra ram 16 bytes CBLOCK 0x190 ENDC ; *** Bank3 *** 80 bytes CBLOCK 0x1A0 ENDC CBLOCK 0x1EB ICD_Reserved2:5 ; for icd 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 0x000 ; processor reset vector NOP ; required for the ICD CLRF STATUS ; ensure we are at bank0 CLRF PCLATH ; ensure page bits are cleared ( before GOTO xxx !!! ) GOTO INIT ; go to initialisation of program ;**************** Interrupt service routine ************************** ORG 0x004 ; interrupt vector location PUSH ; save registers BTFSS PIR1,TMR2IF ; Check TMR2 Overflow GOTO INT_TEST_RX_IRQ ; goto next.... 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: INT_TEST_RX_IRQ BTFSS PIR1,RCIF ; test if serial recive irq GOTO INT_TEST_TX_IRQ ; nope check next ; *********************************************************************** ; RX_INT_HANDLER - handles the received commands on serial com RX_INT_HANDLER BTFSS RCSTA,OERR ; test for overrun error GOTO RX_CHECK_FRAMING ; when overrun, uart will stop receving the continous ; recevive bit must then be reset BCF RCSTA,CREN ; clear continous receve bit BSF RCSTA,CREN ; and set it again RX_CHECK_FRAMING BTFSS RCSTA,FERR ; check from framing errors GOTO RX_CHECK_BUFFER ; framing error do not store this byte ; read rx reg and discard byte GOTO RX_DISCARD_BYTE RX_CHECK_BUFFER MOVF RX_Buffer_Count,W ; test for space XORLW RX_BUFFER_SIZE BTFSC STATUS,Z GOTO RX_BUFFER_FULL ; Place the new char in the RxBuffer MOVF RX_Buffer_InPtr,W ; get adress for indirect dressing MOVWF FSR ; setup fsr MOVF RCREG,W ; get received byte MOVWF INDF ; and store it in buffer INCF RX_Buffer_Count,F ; inc buffer counter ; update pointers INC_BUFFER RX_Buffer_InPtr,RX_Buffer,RX_BUFFER_SIZE BSF GOT_ONE ; set flag GOTO INT_RX_END RX_BUFFER_FULL ; no room for more bytes, set overrun flag BSF _BufferOverrun ; and clear the last byte ( no room to store it ! ) RX_DISCARD_BYTE ; optional an error flag could be set to indicate comm error. MOVF RCREG,W ; read byte and discard ; END RX INT HANDLER INT_RX_END BCF PIR1,RCIF ; clear rx int flag INT_TEST_TX_IRQ BTFSS PIR1,TXIF ; test if serial transmit irq GOTO INT_TEST_NXT ; *********************************************************************** ; TX_INT_HANDLER - handles the tramission of bytes on serial com ; TX_INT_HANDLER MOVF TX_Buffer_Count,W ; get number of bytes BTFSC STATUS,Z ; buffer empty ? GOTO TX_BUFFER_EMPTY MOVF TX_Buffer_OutPtr,W ; get adress for indirect adressing MOVWF FSR ; setup fsr MOVF INDF,W ; get byte MOVWF TXREG ; and put it in tx reg DECF TX_Buffer_Count,F ; decrement buffer counter ; update pointers INC_BUFFER TX_Buffer_OutPtr,TX_Buffer,TX_BUFFER_SIZE GOTO INT_TX_END TX_BUFFER_EMPTY ; no more bytes to send disable TX irq ; code is to avoid bank switching ( using FSR ) MOVLW PIE1 ; get adress for tx irq enable MOVWF FSR ; setup fsr BCF INDF,TXIE ; and disable tx irq INT_TX_END BCF PIR1,TXIF ; clear tx int flag INT_TEST_NXT ; test whatever left :-) INT_EXIT PULL ; restore registers RETFIE ; return from interrupt ; *********************************************************************** ;END INT ROUTINE ; *********************************************************************** ; *********************************************************************** ; INIT - Cold start vector, called at startup ; ; initilaize all ports to known state before setup routines are called ; INIT ; pclath and status is already cleared ! ; before entering this init routine CLRF INTCON ; ensure int reg is clear CLRF PIR1 ; clear periphial irq's CLRF PIR2 ; ditto ; make sure all individual irq's are disabled MOVLW PIE1 ; get adress for periphial irq enable MOVWF FSR ; setup fsr CLRF INDF ; and clear irq enable flags MOVLW PIE2 ; get adress for second periphial irq enable MOVWF FSR ; setup fsr CLRF INDF ; and clear irq enable flags ; note porta as is set as ANALOGUE i/o as default ; clear output data latches CLRF PORTA CLRF PORTB CLRF PORTC ; call initialize routines for periphials/ports ; note must be at bank0 during initializing ; NOTE ! DO NOT CHANGE ORDER OF THESE ROUTINES !! ; clear all user ram ( set to all 0's ) CALL CLEAR_RAM ; setup our ports to in/out/analogue/rx/tx/spi/etc ; must be GOT_ONE before calling any other INIT_XXX routine ; as most of them depends on pin settings CALL INIT_PORTS ; setup uart CALL INIT_UART ; initialize buffers/pointers CALL INIT_BUFFERS ; all pins/periphials configured, enable global irq CALL INIT_TIMER2 ENABLE_IRQ MOVLW LOW OUT0 CALL EE_READ_BYTE ANDLW 0X0F ; MASK THE LOW 4 BITS MOVWF PORTB ; SET OUTPUTS ; init SP variables, bit at address 0,1,2,3 ; output 1 movlw H'A0' call TX_ADD_BUFFER movlw 0 call TX_ADD_BUFFER movf PORTB,w andlw 1 btfss STATUS,Z ; send 0 or 1 movlw 1 call TX_ADD_BUFFER ; output 2 movlw H'A0' call TX_ADD_BUFFER movlw 1 call TX_ADD_BUFFER movf PORTB,w andlw 2 btfss STATUS,Z ; send 0 or 1 movlw 1 call TX_ADD_BUFFER ; output 3 movlw H'A0' call TX_ADD_BUFFER movlw 2 call TX_ADD_BUFFER movf PORTB,w andlw 4 btfss STATUS,Z ; send 0 or 1 movlw 1 call TX_ADD_BUFFER ; output 4 movlw H'A0' call TX_ADD_BUFFER movlw 3 call TX_ADD_BUFFER movf PORTB,w andlw 8 btfss STATUS,Z ; send 0 or 1 movlw 1 call TX_ADD_BUFFER ; display init call init_disp call cur_h1 movlw LOW linie1 movwf comA movlw HIGH linie1 movwf comB call prt_rom ;print the text in Rom (comB:comA) call cur_h2 movlw LOW linie2 movwf comA movlw HIGH linie2 movwf comB call prt_rom ;print the text in Rom (comB:comA) CALL BEEPOK CALL BEEPERR call cur_h2 CALL TESTPASS ; PRINT PASS call cur_h1 CLRF TIME0 ; INIT TIMEOUT COUNTER CLRF TIME1 BSF TIMEOUT ; STOP TIMEOUT COUNTER BCF BAD_SENT ; text not sent ;MAIN_LOOP ; FIRSRT READ #PASS#, WHERE PASS HAS 10 DIGITS main_bad: btfss BAD_SENT call send_bad ; send bad pass string to SP MAIN_START: CALL CLRTIMEOUT MAIN0: BTFSC TIMEOUT GOTO main_bad ; TIMEOUT ERROR, NO SOUND ; FIRST WAIT A DIGIT BTFSS GOT_ONE GOTO MAIN0 ; WE GOT A DIGIT, COMPARE WITH # CALL RX_GET_BUFFER MOVWF RESULT1 XORLW "#" BTFSS STATUS,Z GOTO main_bad ; DIGIT<>#, TRY AGAIN ifdef debug call cur_h1 ;movf RESULT1,w ;call send_c endif 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 GOT_ONE GOTO MAIN1 CALL RX_GET_BUFFER ;MOVWF RESULT1 MOVWF INDF ; PUT DIGIT IN PSS0-9, RAM ifdef debug call send_c endif DECF EE_Byte,F BTFSC STATUS,Z GOTO MAIN21 ; GOT 10 DIGITS INCF FSR,F CALL CLRTIMEOUT GOTO MAIN1 ; WAIT FOR DIGIT 1..9 MAIN21: CALL CLRTIMEOUT MAIN2: ; WAIT # BTFSC TIMEOUT GOTO TIMEO ; TIMEOUT ERROR, RESTART ; WAIT A DIGIT BTFSS GOT_ONE GOTO MAIN2 CALL RX_GET_BUFFER MOVWF RESULT1 XORLW "#" BTFSS STATUS,Z GOTO MAIN_START ; DIGIT<>#, RESTART ifdef debug movf RESULT1,w call send_c endif ; 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 MAIN_START ; 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 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 GOT_ONE GOTO MAIN6 CALL RX_GET_BUFFER ;MOVWF RESULT1 MOVWF INDF ; PUT DIGIT IN PSS0-9, RAM ifdef debug call send_c endif DECF EE_Byte,F BTFSC STATUS,Z GOTO MAIN7 ; GOT 10 DIGITS INCF FSR,F 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 MAIN_START VERIFYOFF: CALL BEEPERR GOTO MAIN_START NOVERIFY: ; GET PSS3,4 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 GOT_ONE GOTO MAIN8 CALL RX_GET_BUFFER ;MOVWF RESULT1 MOVWF INDF ; PUT DIGIT IN PSS0-9, RAM ifdef debug call send_c endif DECF EE_Byte,F BTFSC STATUS,Z GOTO MAIN9 ; GOT 10 DIGITS INCF FSR,F 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 ; PSS0 IS 1..4 >> PSS3 0..3 movf PSS0,W movwf PSS3 ; temp store for the address decf PSS3,f 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 SETOUT 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 SETOUT: ; SEND THE APPROPIATE SEQUENCE TO SITEPLAYER, hA0, ADDRESS, VALUE ; OUT 0 HAS ADDRESS 0 movlw H'A0' call TX_ADD_BUFFER movf PSS3, W call TX_ADD_BUFFER movf PSS2, W call TX_ADD_BUFFER call send_ok ; send the pass ok string CALL BEEPOK ; BEEP HAPPY... goto MAIN_START NOSET: ; CHECK FOR PASS CHANGE ; GET PSS5,10 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 GOT_ONE GOTO MAIN10 CALL RX_GET_BUFFER ;MOVF RESULT1,W MOVWF INDF ; PUT DIGIT IN PSS0-9, RAM ;ifdef debug ;call send_c ;endif DECF EE_Byte,F BTFSC STATUS,Z GOTO MAIN11 ; GOT 10 DIGITS INCF FSR,F CALL CLRTIMEOUT GOTO MAIN10 ; WAIT FOR DIGIT 1..9 MAIN11: ; WAIT FOR # CALL CLRTIMEOUT MAIN12: ; WAIT # BTFSC TIMEOUT GOTO TIMEO ; TIMEOUT ERROR, RESTART ; WAIT A DIGIT BTFSS GOT_ONE GOTO MAIN12 CALL RX_GET_BUFFER MOVWF RESULT1 XORLW "#" BTFSS STATUS,Z GOTO MAIN_START ; DIGIT<>#, RESTART ; GET 10 DIGITS IN DIG_10...DIG1 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 GOT_ONE GOTO MAIN13 CALL RX_GET_BUFFER ;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 CLRTIMEOUT GOTO MAIN13 ; WAIT FOR DIGIT 1..9 MAIN14: ; WAIT FOR # CALL CLRTIMEOUT MAIN15: ; WAIT # BTFSC TIMEOUT GOTO TIMEO ; TIMEOUT ERROR, RESTART ; WAIT A DIGIT BTFSS GOT_ONE GOTO MAIN15 CALL RX_GET_BUFFER ; MOVWF RESULT1 XORLW "#" BTFSS STATUS,Z GOTO MAIN_START ; DIGIT<>#, RESTART CALL CLRTIMEOUT MAIN151: ; WAIT # BTFSC TIMEOUT GOTO TIMEO ; TIMEOUT ERROR, RESTART ; WAIT A DIGIT BTFSS GOT_ONE GOTO MAIN151 CALL RX_GET_BUFFER ; MOVWF RESULT1 XORLW "#" BTFSS STATUS,Z GOTO MAIN_START ; 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 MAIN_START ; 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: ifdef debug call cur_h2 call TESTPASS endif call send_ok ; send pass ok string to SP CALL BEEPOK ; PASS CHANGED GOTO MAIN_START ;*************************************************************** TIMEO: ; TIMEOUT + TIMEOUT BEEP CALL BEEPERR ; TIMEOUT BEEP, TWO LOW BEEPS CALL BEEPPAUSE CALL BEEPERR ;TIMEO1: GOTO MAIN_START ;RESTART ; ****** END MAIN LOOP ; 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 ;********************** ;old main loop ; main loop BTFSS TIMEOUT ; TEST FOR TIMEOUT GOTO NOTIMEOUT ; TIMEOUT OCCURED MOVLW 1 XORWF PORTC,F ; FLIP PORTC0, HEARTBEAT CLRF TIME0 ; INIT TIMEOUT COUNTER CLRF TIME1 BCF TIMEOUT ; START TIMEOUT COUNTER NOTIMEOUT: NOP ; do whatever should be GOT_ONE every loop ; test for specific events MAIN_COM_EVENT ; test if a character is received ( i.e. saved in rx buffer ) CALL RX_GET_BUFFER ; test zero flag BTFSC STATUS,Z GOTO MAIN_GOT_ONE ; nope zero flag set=no byte recieved, test next event ; ***************************** ; a byte is recevied ! ; ***************************** movwf scrA CALL TX_ADD_BUFFER movf scrA, W call send_c MAIN_GOT_ONE NOP ; and return to main loop ; GOTO MAIN_LOOP ;to be deleted ; *********************************************************************** ; ; CLEAR_RAM - Reset all general purpose ram to 0's ; Note ! does not clear watchdog, add CLRWDT where appropiate if enabled ; Make sure to be at bank0 ; CLEAR_RAM MOVLW 0x20 ; start ram bank0 MOVWF FSR CLEAR_BANK0 CLRF INDF ; Clear a register pointed to be FSR INCF FSR,F MOVLW 0x7F ; Test if at top of memory bank0 SUBWF FSR,W BNZ CLEAR_BANK0 ; Loop until all cleared MOVLW 0xA0 ; start ram bank1 MOVWF FSR CLEAR_BANK1 CLRF INDF ; Clear a register pointed to be FSR INCF FSR,F ; note this could also be set to 0xFF or 0xEF as the top 16 bytes are mirrored from ; bank0 MOVLW 0xEF ; Test if at top of memory bank1 SUBWF FSR,W BNZ CLEAR_BANK1 ; Loop until all cleared BANK2 ; select bank2/3 ( with indirect adressing ) MOVLW 0x10 ; start ram bank2 MOVWF FSR CLEAR_BANK2 CLRF INDF ; Clear a register pointed to be FSR INCF FSR,F ; note this could also be set to 0x7F or 0x70 as the top 16 bytes are mirrored from ; bank0 MOVLW 0x70 ; Test if at top of memory bank2 SUBWF FSR,W BNZ CLEAR_BANK2 ; Loop until all cleared MOVLW 0x90 ; start ram bank3 MOVWF FSR CLEAR_BANK3 CLRF INDF ; Clear a register pointed to be FSR INCF FSR,F ; note this could also be set to 0xFF or 0xEF as the top 16 bytes are mirrored from ; bank0 MOVLW 0xEF ; Test if at top of memory bank3 SUBWF FSR,W BNZ CLEAR_BANK3 ; Loop until all cleared BANK0 ; set back to bank0 RETURN ; *********************************************************************** ; ; INIT_PORTS - Initialises all ports on the PIC ; i.e sets the pins as in/out/analog/etc ; Make sure to be at bank0 INIT_PORTS ; setup PORTA ; set RA0 analogue and the rest of the pins digital MOVLW ADCON1 ; get adress for ad/module config1 reg MOVWF FSR ; setup fsr MOVLW (1<high, prescaler to Timer0, TMR0 rate 1:2 MOVWF INDF ; and set it RETURN ; *********************************************************************** ; ; INIT_UART - Initialises UART ; enables recevier and transmitter ; Make sure to be at bank0 INIT_UART ; make sure pins are setup before calling this routine ; TRISC:6 and TRISC:7 must be set ( as for output, but operates as input/output ) ; furthermore its advised that interrupts are disabled during this routine ; setup baudrate MOVLW SPBRG ; get adress for serial baud reg MOVWF FSR ; setup fsr MOVLW CALC_HIGH_BAUD(9600) ; calculate baudrate is this example 9600 with brgh=1 MOVWF INDF ; and store it ; enable transmitter MOVLW TXSTA ; get adress for serial enable reg MOVWF FSR ; setup fsr MOVLW (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 ; EE_WRITE_BYTE - Routine to write a byte to EEram - Adress in W, byte MUST be in EE_Byte ; EE_READ_BYTE - Routine to read a byte from EEram - Adress in W, byte will be delivered 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 disp_clear: movlw 0x1 ; display clear call send_b movlw 30 ; 2 ms delay to clear the display call del_1mx return ;************************************************************************ ; send the string located at (comB:comA) in program memory to serial buffer ser_rom: Bank2 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 ser_rom2 Bank0 call TX_ADD_BUFFER ; print char in w+100uS wait incfsz comA, F goto ser_rom incf comB, F goto ser_rom ser_rom2: Bank0 movlw CR call TX_ADD_BUFFER movlw LF call TX_ADD_BUFFER return ;************************************************************************ ; send comC bytes from the string located at (comB:comA) in program memory to serial buffer ( SEND STRING TO SP) ser_romSP: Bank2 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 Bank0 call TX_ADD_BUFFER ; send char to serial decf comC, f ; decrement counter btfsc STATUS, Z goto ser_romSP1 ser_romSP2: incfsz comA, F goto ser_romSP incf comB, F goto ser_romSP ser_romSP1: Bank0 return ;************************************************************************ ; send ok message to SP, 2 strings at addr 0 and 10 send_ok: movlw H'8F' ; write byte, 16 call TX_ADD_BUFFER movlw H'0' ; address call TX_ADD_BUFFER movlw LOW passok1 movwf comA movlw HIGH passok1 movwf comB movlw .16 movwf comC call ser_romSP ;send str to SP movlw H'8F' ; write byte, 16 call TX_ADD_BUFFER movlw H'10' ; address call TX_ADD_BUFFER movlw LOW passok2 movwf comA movlw HIGH passok2 movwf comB movlw .16 movwf comC call ser_romSP ;send str to SP BCF BAD_SENT ; ok sent return ;************************************************************************ ; send bad message to SP, 2 strings at addr 0 and 10 send_bad: movlw H'8F' ; write byte, 16 call TX_ADD_BUFFER movlw H'0' ; address call TX_ADD_BUFFER movlw LOW passbad1 movwf comA movlw HIGH passbad1 movwf comB movlw .16 movwf comC call ser_romSP ;send str to SP movlw H'8F' ; write byte, 16 call TX_ADD_BUFFER movlw H'10' ; address call TX_ADD_BUFFER movlw LOW passbad2 movwf comA movlw HIGH passbad2 movwf comB movlw .16 movwf comC call ser_romSP ;send str to SP BSF BAD_SENT ; bad sent return ;************************************************************************ ser_ram: ;send from RAM, string located at (IRP:W) movwf FSR ser_ram1: movlw 0 subwf INDF, w ; compare 0 btfsc STATUS, Z return ; char = zero movf INDF, W CALL TX_ADD_BUFFER incf FSR, F goto ser_ram1 ;************************************************************************ ;EEprom routines by Tony Kubek ; *********************************************************************** ; 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 ;*************************************************************************** ; test strings linie1: DE "Internet Plug II",0 linie2: DE "by Radu (c)2002",0 linie3: DE "1234567890123456",0 linie4: DE "1234567890123456",0 passok1: DE "Password OK " ; pass ok passok2: DE "Output Set " passbad1: DE "WRONG Password " ; pass wrong passbad2: DE "Try again! " out0off: DE H'A0',0,0 ; A0 write one bit variable, address, value out0on: DE H'A0',0,1 out1off: DE H'A0',1,0 ; A0 write one bit variable, address, value out1on: DE H'A0',1,1 out2off: DE H'A0',2,0 ; A0 write one bit variable, address, value out2on: DE H'A0',2,1 out3off: DE H'A0',3,0 ; A0 write one bit variable, address, value out3on: DE H'A0',3,1 END