;****************************************************************************** ; DECODIFICADOR DE HCS200 ...301 COM NUCLEO 8051 - (AT89C2051) - 08/11/2010 ; ; APLICAÇÃO GENERICA ; BY CLÁUDIO LÁRIOS ; ; ; Utiliza uma memória 24c02 OU 24C04 (METADE) para armazenar dados dos códigos dos ; transmissores permitidos. ; PINAGENS: ; PINO 1= RESET - LIGAR A MASSA 22K E CAPACITOR 1UF AO VCC ; PINO 2/8/9/11/18/19= NÃO USADOS ; PINO 3= ENTRADA DO SINAL A DECODIFICAR VIA RESISTOR DE 330 OHMS A 1K ; PINO 4/5= XTAL DE 12MHZ ; PINO 6= AO VCC VIA RESISTORDE 10K E AO BOTÃO DE 'LEARN' A MASSA ; PINO 7= RESISTOR DE 470 OHMS AO LED DE 'LEARN' A MASSA. ; PINO 10= GND ; PINO 12= SAIDA 'S0' 1=SINAL OK ; PINO 13= SAIDA 'S1' 1=SINAL OK ; PINO 14= SAIDA 'S2' 1=SINAL OK ; PINO 15= SAIDA 'S3' 1=SINAL OK ; PINO 16= SDA DA 24C04 ; PINO 17= SCL DA 24C04 ; PINO 20= VCC (+5V) ; ; USE XTAL 12MHZ ;----------------------------------------------------------------------------- MAX_USERS EQU 30 ; Este é o numero maximo de transmissores que esta apto a receber (1 to 30). ; (Pode ser ajustado conforme o tipo de memória a ser usada.) ;------------------------------------------------------------------------------ CTIMEMAXL EQU 200 ;TEMPO MAXIMO DE UM TE' CTIMEMAXH EQU 3 ;------------------------------------------------------------------------------- ; GENERAL PURPOSE REGISTERS IND EQU R0 ; INDIRECT ADDRESS REGISTER RTCC EQU TH0 ; REAL TIME COUNTER CLOCK STATUS EQU PSW ; STATUS REGISTER PORTA EQU P3 ; PORT A DE P3,0 A P3,5 E 3.7 (INCOMPLETA) PORTB EQU P1 ; PORT B P1 DE P1,0 A P1,7 (COMPLETA) ; USER DEFINED REGISTER ; ENDEREÇO 20H RESERVADO PARA MACROS PIC TEMP EQU 20H FLAGS DATA 39H ; USER FLAG REGISTER ADDRESS DATA 21H ; ADDRESS REGISTER TXNUM DATA 32H ; CURRENT TX OUTBYT DATA 23H ; GENERAL DATA REGISTER MASK EQU OUTBYT ; MASK REGISTER USED IN DECRYPTION TMP_CNT EQU OUTBYT ; TEMPORARY COUNTER ; COUNTER REGISTERS CNT0 EQU 24H ; LOOP COUNTERS CNT1 EQU 25H CNT2 EQU 26H NTE EQU 40H CNTH EQU 41H CNTL EQU 42H W_SALVO EQU 43H DYTA EQU 50H ;DADOS DE ENTRADA E SAIDA NO I2C MEMORY CNT_HI EQU 27H ; 16 BIT CLOCK COUNTER CNT_LW EQU 28H ; CIRCULAR BUFFER REGISTER CSR0 EQU 29H ; 64 BIT RECEIVE SHIFT REGISTER CSR1 EQU 2AH CSR2 EQU 2BH CSR3 EQU 2CH CSR4 EQU 2DH CSR5 EQU 2EH CSR6 EQU 2FH CSR7 EQU 30H ; TEMP REGISTERS TMP1 EQU 31H ; TEMP REGISTER FOR READ AND WRITE TMP2 EQU 22H ; TEMP REGISTER FOR READ AND WRITE REG EQU 33H ; NOT USED REG1 EQU 34H ; NOT USED KEY0 EQU 35H ; 64 BIT KEY SHIFT REGISTER KEY1 EQU 36H KEY2 EQU 37H KEY3 EQU 38H KEY4 EQU CNT2 KEY5 EQU CSR5 KEY6 EQU CSR6 KEY7 EQU CSR7 ; ***** USER REGISTER RE-MAPPINGS *************** HOP1 EQU CSR0 ; 32 BIT HOPCODE REGISTER HOP2 EQU CSR1 HOP3 EQU CSR2 HOP4 EQU CSR3 ; RECEIVED TRANSMISSION OPEN 32 BITS SER_0 EQU CSR7 ; 28 BIT SERIAL NUMBER SER_1 EQU CSR6 SER_2 EQU CSR5 SER_3 EQU CSR4 ; RECEIVED TRANSMISSION ENCRYPTED 32 BITS FUNC EQU CSR3 ; BUTTON CODE & USER BIT FUNCTION BYTE DISC EQU CSR2 ; DISCRIMINATION VALUE CNTR_HI EQU CSR1 ; 16 BIT RX COUNTER HIGH BYTE CNTR_LW EQU CSR0 ; 16 BIT RX COUNTER LOW BYTE ; ********* EEPROM MEMORY ******* LRNPTR EQU 0FEH ; LEARN POINTER (PENULTIMA POSIÇÃO DA MEMÓRIA DO 2402) ; ********* PORTA BIT DEFINITIONS ******* ; OBS: PINAGEM SE REFERE AO AT89S52 (ENTRE PARENTESES DO AT89C2051) RES0 EQU 0H ; RESERVED PIN RFIN EQU 1H ; RF INPUT PINO 11(3) (P3.1) LRN EQU 2H ; LEARN BUTTON PINO 12(6) (P3.2) LED EQU 3H ; LEARN INDICATOR LED OUTPUT - VALID SIGNAL PINO 13(7) (P3.3) ; ********* PORTB BIT DEFINITIONS ******* S0 EQU 0H ; S0 OUTPUT PINO 1 (12) (P1.0) S1 EQU 1H ; S1 OUTPUT PINO 2 (13) (P1.1) S2 EQU 2H ; S2 OUTPUT PINO 3 (14) (P1.2) S3 EQU 3H ; S3 OUTPUT PINO 4 (15) (P1.3) RES1 EQU 7H ; RESERVED PIN RES2 EQU 6H ; RESERVED PIN SDA EQU PORTB.4 ; LINHA DE DADOS DA 24C02 PINO 5(16) (P1.4) SCL EQU PORTB.5 ; LINHA DE CLOCK DA 24C02 PINO 6(17) (P1.5) ; ********* COMPILER DEFINES ****************** NBITS EQU 64 ; MAXIMUM TRANSMISSION BIT LENGTH MIN EQU 560 ; TRANSMISSION HEADER MINIMUM LENGTH [ S] ;****** FLAGS DEFINITIONS ************** BITIN EQU 0H ; RF BIT VALUE LRNF EQU 1H ; LEARN FLAG SEC_CNT EQU 2H ; SECOND COUNTER IS BEING CHECKED RELEARN EQU 3H ; RELEARNING A TRANSMITTER VAL EQU 4H ; PERIODO DO TE CAPTADO ;------------------------------------------------------------------------------ ; PAGE 0: ;------------------------------------------------------------------------------ ORG 00H AJMP RESETA ;------------------------------------------------------------------------------ ; ; FUNCTION : RESET () ; ; DESCRIPTION : PROGRAM RESET ROUTINE ; ;------------------------------------------------------------------------------ ORG 30H RESETA: MOV A,#1H MOV TMOD,A MOV A,# 00010000B ;ACERTA TIMER 0 PARA 16 BIT E LIGA MOV TCON,A MOV PORTA,#0H ;CLRF PORTA ; RESET PORTA MOV PORTB,#0H ;CLRF PORTB ; RESET PORTB MOV P2,#0H MOV FLAGS,#0H ;CLRF FLAGS; RESET FLAGS AJMP M_LOOP ; GOTO MAIN PROGRAM LOOP ;----------------------------------------------------------------------------- ; ; I2C ROTINAS ; Utilize 24c02 ou 24c04. ;------------------------------------------------------------------------------- I2C_READ: ;reading 8 bits from i2c device MOV R7,#8 GFD: SETB SDA ;LEVANTA PARA LEITURA SETB SCL MOV C,SDA RLC A NOP CLR SCL DJNZ R7,GFD RET I2C_WRITE: ;writing 8 bits in to i2c device MOV R7,#8 WRITING: RLC A MOV SDA,C LCALL CLOCK DJNZ R7,WRITING RET I2C_START: ;start of i2c routine SETB SCL SETB SDA NOP CLR SDA NOP CLR SCL RET I2C_STOP: ;end of i2c routine CLR SDA SETB SCL NOP SETB SDA NOP CLR SCL RET CLOCK: ;synchronizing clock SETB SCL NOP NOP NOP NOP CLR SCL RET ACK: ;acknowledge from transmitter or receiver SETB SDA SETB SCL JB SDA,$ CLR SCL RET NO_ACK: ;no acknowledge from transmitter or receiver SETB SDA NOP CLR SCL NOP JNB SDA,$ NOP SETB SCL RET ;************************* ;SERIAL EEPROM PACKAGE**** ;************************* EEWRITE: MOV DYTA,TMP1 ACALL EEWRITE1 INC ADDRESS MOV DYTA,TMP2 ACALL EEWRITE1 INC ADDRESS RET EEREAD: ACALL EEREAD1 MOV TMP1,DYTA INC ADDRESS ACALL EEREAD1 MOV TMP2,DYTA RET ;---------------------------------OK-------- EEWRITE1: ;COLOQUE ENDEREÇO EM 'ADDRESS' E DADO EM 'DYTA' EEPROM_WRITE: ;write in to eeprom LCALL I2C_START LCALL EEPROM_WRITE_ADDR LCALL ACK ;MOV A,#0 ;USE SOMENTE PARA ADDRESS DUPLO ;LCALL I2C_WRITE ;LCALL ACK MOV A,ADDRESS LCALL I2C_WRITE LCALL ACK MOV A,DYTA LCALL I2C_WRITE LCALL ACK LCALL I2C_STOP LCALL DELAY_STOP RET ;-------------------------------------------------OK----------- EEREAD1: ;COLOQUE ENDEREÇO EM 'ADDRESS' E RECEBA O DADO EM 'DYTA' EEPROM_READ: ;read from eeprom LCALL I2C_START LCALL EEPROM_WRITE_ADDR LCALL ACK ;MOV A,#0 ;SOMENTE PARA MEMORIAS COM ENDEREÇO DUPLO ;LCALL I2C_WRITE ;LCALL ACK MOV A,ADDRESS LCALL I2C_WRITE LCALL ACK LCALL I2C_START LCALL EEPROM_READ_ADDR LCALL ACK LCALL I2C_READ LCALL NO_ACK LCALL I2C_STOP MOV DYTA,A RET ;-------------------------------------------- EEPROM_READ_ADDR: ;A2,A1,A0 are zero MOV A,#10100001B LCALL I2C_WRITE RET EEPROM_WRITE_ADDR: ;A2,A1,A0 are zero MOV A,#10100000B LCALL I2C_WRITE RET DELAY_STOP: ;terminating write process MOV R4,#20 VH1: MOV R3,#250 DJNZ R3,$ DJNZ R4,VH1 RET ;------------------------------------------------------------- EEERASE: ;APAGA TODAS AS POSIÇÕES DE MEMÓRIA SELECIONADA EM A0 (1=PAGINA HIGH/0=PAG LOW) MOV R6,#32 ;32 PAGINAS DE 8 BYTES MOV R5,#8 ; 8 BYTES POR PAGINA MOV ADDRESS,#0H EET1: LCALL I2C_START LCALL EEPROM_WRITE_ADDR LCALL ACK MOV A,ADDRESS LCALL I2C_WRITE LCALL ACK EET2: MOV A,#0FFH LCALL I2C_WRITE LCALL ACK DJNZ R5,EET2 LCALL I2C_STOP ACALL DELAY_STOP ; TEMPO DE GRAVAÇÃO MOV A,#8 ADD A,ADDRESS MOV ADDRESS,A DJNZ R6,EET1 LCALL DELAY_STOP RET ;------------------------------------------------------------------------------ ; ; FUNCTION : ROT_SHIFT() ; ; DESCRIPTION : RIGHT ROTATE 64 BIT RECEIVE SHIFT REGISTER ; ; ;------------------------------------------------------------------------------ ROT_SHIFT: MOV A,CSR7 RRC A MOV CSR7,A MOV A,CSR6 RRC A MOV CSR6,A MOV A,CSR5 RRC A MOV CSR5,A MOV A,CSR4 RRC A MOV CSR4,A MOV A,CSR3 RRC A MOV CSR3,A MOV A,CSR2 RRC A MOV CSR2,A MOV A,CSR1 RRC A MOV CSR1,A MOV A,CSR0 RRC A MOV CSR0,A RET ;----------------------------------------------------------------------------- ; ; FUNCTION : TX_LOOKUP () ; ; DESCRIPTION : TRANSMITTER ADDRESS CALCULATION ; ; NOTE : THIS ROUTINE MUST BE IN THE LOWER HALF OF THE PAGE ; ;------------------------------------------------------------------------------ TX_LOOKUP: MOV A,TXNUM ; USE TRANSMITTER NUMBER TO CALCULATE MOV ADDRESS,A ;ADDRESS OF TRANSMITER BLOCK CLR C MOV A,ADDRESS RLC A RLC A RLC A ; MULTIPLY BY 8 MOV ADDRESS,A RET ;------------------------------------------------------------------------------ ; ; FUNCTION : TST_RTCC () ; ; DESCRIPTION : UPDATE RTCC COUNTER ; ; NOTE : THIS ROUTINE MUST BE IN THE LOWER HALF OF THE PAGE ; ;------------------------------------------------------------------------------ TST_RTCC: MOV TEMP,RTCC ;COLOCA EM REGISTRADOR QUE PERMITE LEITURA DE BIT JB TEMP.7 ,J001 ; TEST FOR 32MS TIMEOUT ON RTCC MSB RET ; ... DO QUICK RETURN TO RECEIVE ROUTINE ; **** INCREASE 16 BIT CLOCK TIMER ******* J001: CLR TEMP.7 ; CLEAR MSB OF RTCC MOV RTCC,TEMP INC CNT_LW ; INCREASE 16 COUNTER MOV A,CNT_LW ;TESTA EM ACC SE = 0 JNZ J002 ; INCREASE UPPER BYTE IF ZERO ( OVERFLOW ) INC CNT_HI J002: RET ;------------------------------------------------------------------------------ ; ; FUNCTION : TST_TIMER() ; ; DESCRIPTION : TEST 32MS TIMER AND UPDATE OUTPUTS IF REQUIRED ; ; ;------------------------------------------------------------------------------ TST_TIMER: ; ***** TEST FOR 500 MS TIMEMOUT ON OUTPUTS ********** JB CNT_LW.4 , J003 ; TEST FOR 500 MS TIMEOUT AJMP TST_30 ; ... IF NOT TEST 30S TIMEOUT J003: MOV A,#0F0H ANL A,PORTB ; DOWN ALL PULSE OUTPUTS MOV PORTB,A ; ********* TEST FOR 30 S LEARN TIMEOUT ************* TST_30: MOV TEMP,FLAGS JB TEMP.LRNF , J004 AJMP TST_END J004: JNB CNT_HI.2 , J005 ; TEST FOR LEARN TIMEOUT AJMP RESETA ; ... IF LEARN TIMEMOUT FORCE SOFT RESET J005: TST_END: RET ;------------------------------------------------------------------------------ ; ; FUNCTION : DECRYPT () ; ; DESCRIPTION : DECRYPTS 32 BIT [HOP1:HOP4] USING [CSR0:CSR7] ;------------------------------------------------------------------------------ ; THE KEY USED IS A FIXED KEY WHICH IS NOT SERIAL NUMBER DEPENDANT ; THE USER MUST CHOOSE A KEY AND CHANGE THE CODE HERE TO REFLECT THAT KEY DECRYPT: MOV KEY0,#01H ; LOAD FIXED 64 BIT KEY LSB MOV KEY1,#23H MOV KEY2,#45H MOV KEY3,#67H MOV KEY4,#89H MOV KEY5,#0ABH MOV KEY6,#0CDH ; LOAD FIXED 64 BIT KEY MSB MOV KEY7,#0EFH MOV CNT1,#12D ; OUTER LOOP 11+1 TIMES DECRYPT_OUTER: MOV CNT0,#48D ; INNER LOOP 48 TIMES DECRYPT_INNER: MOV A,CNT1 ; LAST 48 LOOPS RESTORE THE KEY XRL A,#1 ; LAST 48 LOOPS RESTORE THE KEY JNZ J015 ; LAST 48 LOOPS RESTORE THE KEY AJMP ROTATE_KEY ; LAST 48 LOOPS RESTORE THE KEY ; THE LOOKUP TABLE IS COMPRESSED INTO IN 4 BYTES TO SAVE SPACE ; USE THE 3 LOW INDEX BITS TO MAKE UP AN 8-BIT BIT MASK ; USE THE 2 HIGH INDEX BITS TO LOOK UP THE VALUE IN THE TABLE ; USE THE BIT MASK TO ISOLATE THE CORRECT BIT IN THE BYTE ; PART OF THE REASON FOR THIS SCHEME IS BECAUSE NORMAL TABLE LOOKUP ; REQUIRES AN ADDITIONAL STACK LEVEL J015: CLR C ; CLEAR CARRY (FOR THE LEFT SHIFT) MOV A,#1 ; INITIALISE MASK = 1 MOV TEMP,HOP3 ;REGISTRADOR NÃO OPERA COM BITS JNB TEMP.3 ,J016 ; SHIFT MASK 4X IF BIT 2 SET MOV A,#10000B ; SHIFT MASK 4X IF BIT 2 SET J016: MOV MASK,A ; INITIALISE MASK = 1 MOV TEMP,HOP2 ;REGISTRADOR NÃO OPERA COM BITS JB TEMP.0 ,J017 ; SHIFT MASK ANOTHER 2X IF BIT 1 SET AJMP JJ1 J017: MOV A,MASK RLC A RLC A MOV MASK,A JJ1: MOV TEMP,HOP1 ;REGISTRADOR NÃO OPERA COM BITS JNB TEMP.0 ,J018 ; SHIFT MASK ANOTHER 1X IF BIT 0 SET MOV A,MASK RLC A MOV MASK,A ; MASK HAS NOW BEEN SHIFTED 0-7 TIMES ACCORDING TO BITS 2:1:0 MOV DPTR,#TABLE ;PEGA ENDEREÇO DA TABELA J018: MOV A,#0H ; TABLE INDEX = 0 MOV TEMP,HOP4 JNB TEMP.1 ,J019 ORL A,#1 ; IF BIT 3 SET ADD 1 TO THE TABLE INDEX J019: MOV TEMP,HOP4 JNB TEMP.6 , J020 ORL A,#2H ; IF BIT 4 SET ADD 2 TO THE TABLE INDEX J020: MOVC A,@A+DPTR ; PEGA VALOR DA TABELA EM ACC ; [ MUST BE IN LOWER HALF OF PAGE ] AJMP TABLE_END TABLE: DB 02EH ; BITS 4:3 WERE 00 DB 074H ; BITS 4:3 WERE 01 DB 05CH ; BITS 4:3 WERE 10 DB 03AH ; BITS 4:3 WERE 11 TABLE_END: ANL A,MASK ; ISOLATE THE CORRECT BIT BY ANDING WITH MASK MOV MASK,A MOV R2,#0H ; COPY THE BIT TO BIT 7 JZ J021 ; COPY THE BIT TO BIT 7 MOV R2,#10000000B ; COPY THE BIT TO BIT 7 J021: MOV A,R2 XRL A,HOP2 ; ONLY INTERESTED IN BIT HOP2,7 XRL A,HOP4 ; ONLY INTERESTED IN BIT HOP4,7 XRL A,KEY1 ; ONLY INTERESTED IN BIT KEYREG1,7 ; MOV MASK,A ; STORE ACC TEMPORARILY (WE NEED BIT 7) ;MOV A,MASK RLC A ; LEFT ROTATE MASK TO GET BIT 7 INTO THE CARRY MOV MASK,A MOV A,HOP1 RLC A ; SHIFT IN THE NEW BIT MOV HOP1,A MOV A,HOP2 RLC A ; SHIFT IN THE NEW BIT MOV HOP2,A MOV A,HOP3 RLC A ; SHIFT IN THE NEW BIT MOV HOP3,A MOV A,HOP4 RLC A ; SHIFT IN THE NEW BIT MOV HOP4,A ROTATE_KEY: CLR C ; CLEAR CARRY MOV TEMP,KEY7 JNB TEMP.7 ,J022 ; SET CARRY IF LEFTMOST BIT SET SETB C ; SET CARRY IF LEFTMOST BIT SET J022: MOV A,KEY0 ; LEFT-ROTATE THE 64-BIT KEY RLC A MOV KEY0,A MOV A,KEY1 RLC A MOV KEY1,A MOV A,KEY2 RLC A MOV KEY2,A MOV A,KEY3 RLC A MOV KEY3,A MOV A,KEY4 RLC A MOV KEY4,A MOV A,KEY5 RLC A MOV KEY5,A MOV A,KEY6 RLC A MOV KEY6,A MOV A,KEY7 RLC A MOV KEY7,A DJNZ CNT0 ,DECRYPT_INNER1 ; INNER LOOP 48 TIMES DJNZ CNT1 ,DECRYPT_OUTER1 ; OUTER LOOP 12 TIMES (11 + 1 TO RESTORE KEY) RET ; RETURN DECRYPT_INNER1: ;AUXILIARES DE JUMP LONGO AJMP DECRYPT_INNER DECRYPT_OUTER1: AJMP DECRYPT_OUTER ;------------------------------------------------------------------------------ ; ; FUNCTION : LOAD_CNT_VALS() ; ; DESCRIPTION : LOAD COUNTERS INTO WRITE BUFFERS ; ; NOTE : THIS ROUTINE MUST BE IN THE LOWER HALF OF THE PAGE ; ;------------------------------------------------------------------------------ LOAD_CNT_VALS: MOV TMP1,CNTR_HI ; LOAD MSB OF COUNTER MOV TMP2,CNTR_LW ; LOAD LSB OF COUNTER RET ;----------------------------------------------------------------------------- ; FUNÇÃO ABAIXO SOMENTE PARA TESTE ;------------------------------------------------------------------------------ ; ; FUNCTION : ENCRYPT() ; ; DESCRIPTION : ENCRIPTAR CODIGO ; ;------------------------------------------------------------------------------ ; MUDE AQUI PARA USA 'KEY' SE DESEJAR E USE A MESMA NO HCS ENCODER 200...301 ENCRYPT: MOV KEY0,#01H ; LOAD FIXED 64 BIT KEY LSB MOV KEY1,#23H MOV KEY2,#45H MOV KEY3,#67H MOV KEY4,#89H MOV KEY5,#0ABH MOV KEY6,#0CDH ; LOAD FIXED 64 BIT KEY MSB MOV KEY7,#0EFH MOV CNT1,#11D ; OUTER LOOP 11 TIMES MOV CNT0 ,#48D ; INNER LOOP 48 TIMES VC: ACALL ROTATE_RKEY ;RODA A CHAVE INICIALMENTE 48 X DJNZ CNT0,VC ENCRYPT_OUTER: MOV CNT0 ,#48D ; INNER LOOP 48 TIMES ENCRYPT_INNER: ; RODA A CHAVE ACALL ROTATE_RKEY ;RODA A CHAVE ; RODA HOPPING CLR C ;APAGA STATUS,C ; SHIFT IN THE NEW BIT MOV A,HOP4 RRC A MOV HOP4,A MOV A,HOP3 RRC A MOV HOP3,A MOV A,HOP2 RRC A MOV HOP2,A MOV A,HOP1 RRC A MOV HOP1,A JC AL1 MOV W_SALVO,#0H AJMP SR3 AL1: MOV W_SALVO,#10000000B ;SALVA HOP1,0 EM W_SALVO ;RECUPERA HOP4,7 SR3: CLR C ; CLEAR CARRY (FOR THE LEFT SHIFT) MOV TEMP,HOP3 JB TEMP.3,SR5 ; INITIALISE MASK = 1 MOV MASK,#1 ; SHIFT MASK 4X IF BIT 2 SET AJMP SR6 SR5: MOV MASK,#10000B SR6: MOV TEMP,HOP2 JB TEMP.0,SR7 ; INITIALISE MASK = 1 AJMP SR8 SR7: MOV A,MASK ; SHIFT MASK ANOTHER 2X IF BIT 1 SET RLC A RLC A MOV MASK,A SR8: MOV TEMP,HOP1 JB TEMP.0,SR9 ; INITIALISE MASK = 1 AJMP SR10 SR9: MOV A,MASK ; SHIFT MASK ANOTHER 1X IF BIT 1 SET RLC A MOV MASK,A SR10: ; MASK HAS NOW BEEN SHIFTED 0-7 TIMES ACCORDING TO BITS 2:1:0 MOV A,#0H ; TABLE INDEX = 0 MOV TEMP,HOP4 ; IF BIT 3 SET ADD 2 TO THE TABLE INDEX JB TEMP.1, SR11 AJMP SR12 SR11: ORL A,#1H SR12: JB TEMP.6,SR13 AJMP SR14 SR13: ORL A,#2H SR14: MOV DPTR,#TABELA MOVC A,@A+DPTR AJMP SEGT TABELA: DB 2EH ; BITS 4:3 WERE 00 DB 74H ; BITS 4:3 WERE 01 DB 5CH ; BITS 4:3 WERE 10 DB 3AH ; BITS 4:3 WERE 11 SEGT: ANL A,MASK ; ISOLATE THE CORRECT BIT BY ANDING WITH MASK MOV MASK,A JZ SDW1 MOV A,#10000000B SDW1: XRL A,KEY1 ; ONLY INTERESTED IN BIT KEYREG1,7 XRL A,W_SALVO ; ONLY INTERESTED IN BIT HOP4,7 RECUPERADO EM W_SALVO XRL A,HOP2 ;ONLY INTERESTED IN BIT HOP2,7 MOV MASK,A ; STORE W TEMPORARILY (WE NEED BIT 7) JB MASK.7,SDW2 MOV TEMP,HOP4 ; CLR TEMP.7 MOV HOP4,TEMP AJMP ST4 SDW2: MOV TEMP,HOP4 SETB TEMP.7 MOV HOP4,TEMP ;RECUPERA HOP4,7 QUE ESTAVA PERDIDO ST4: ;RODA PARA DIREITA A PARTIR DO BIT 0 DJNZ CNT0,ENCRYPT_INNERX ; INNER LOOP 48 TIMES DJNZ CNT1,ENCRYPT_OUTERX ; OUTER LOOP 12 TIMES (11 + 1 TO RESTORE KEY) RET ENCRYPT_INNERX : AJMP ENCRYPT_INNER ENCRYPT_OUTERX : AJMP ENCRYPT_OUTER ; AUXILIAR DE JUMP LONGO ;-------------------------------------------------------------- ROTATE_RKEY: CLR C ; CLEAR CARRY MOV TEMP,KEY0 JB TEMP.0,RE57 AJMP RE58 RE57: SETB C ; SET CARRY IF RIGHLOW BIT SET RE58: MOV A,KEY7 RRC A MOV KEY7,A MOV A,KEY6 RRC A MOV KEY6,A MOV A,KEY5 RRC A MOV KEY5,A MOV A,KEY4 RRC A MOV KEY4,A MOV A,KEY3 RRC A MOV KEY3,A MOV A,KEY2 RRC A MOV KEY2,A MOV A,KEY1 RRC A MOV KEY1,A MOV A,KEY0 RRC A MOV KEY0,A ; RIGHT-ROTATE THE 64-BIT KEY RET ;------------------------------------------------------------------------------ ; ; FUNCTION : RECEIVE() ; ; DESCRIPTION : RECEPTION ROUTINE FOR PWM TRANSMISSIONS ; ;------------------------------------------------------------------------------ RECEIVE: ;******** WAIT FOR HEADER AND CALIBRATE ******************* SETB PORTA.RFIN ;LEVANTA PARA LEITURA JB PORTA.RFIN ,J025 ; INPUT HIGH? AJMP RMT_0 ; NO; RECEIVE ERROR J025: MOV CNT1,#10D ;10 - 10 ms TIMER RCV0: MOV CNT0,#200D RCV1: SETB PORTA.RFIN ;LEVANTA PARA LEITURA JB PORTA.RFIN ,J026 ; [2] INPUT HIGH? AJMP RCV2 ; [0] NO, JUMP OUT OF LOOP J026: DJNZ CNT0 ,RCV1 ; [1] YES, CONTINUE WITH TIMING LOOP ; [2] 5 us X CNT0 DJNZ CNT1 ,RCV0 ; [0] DO 1 ms LOOP CNT1 TIMES ; [0] RCV2: MOV A,#0H MOV CNT0,A ; [1] CLEAR CALIB COUNTER LOW BYTE MOV CNT1,A ; [1] CLEAR CALIB COUNTER HIGH BYTE ;************************************************************************* ; 2.5 IS AVERAGE FOR DETECTING FALLING EDGE IN RCV1 ; 2 INSTRUCTIONS FOR JUMP OUT RCV1 TO RCV2 ; 2 INSTRUCTIONS FOR RCV2 - CLEAR CALIBRATION COUNTER ; TOTAL 6.5 INSTRUCTIONS < 1 CALIBRATION LOOP SO DISCARD ;************************************************************************* RCV3: SETB PORTA.RFIN ;(1) LEVANTA PARA LEITURA JNB PORTA.RFIN ,J029 ;(2) INPUT HIGH? AJMP RCV6 ;(2) YES--END CALIBRATION J029: INC CNT0 ;(1) INCREMENT 16BIT COUNTER MOV A,CNT0 ;(1) JNZ J030 ;(2) INC CNT1 ;(1) J030: JB CNT1.3 , J031 ;(2) ULTRAPASSOU CONTAGEM MAXIMA ESPERADA AJMP RCV3 ;(2) VOLTA AO LOOP ATÉ RFIN=1 J031: AJMP RMT_0 ; [0] ERRO - SAI E VOLTA AO PROGRAMA PRINCIPAL ; TOTAL = 10 RCV6: CLR C ;(1) DIVIDE CNT1:CNT0 BY 8 (600/8=75) MOV A,CNT1 ;(1) RRC A ;(1) MOV CNT1,A ;(1) MOV A,CNT0 ;(1) RRC A ;(1) MOV CNT0,A ;(1) MOV A,CNT1 ;(1) RRC A ;(1) MOV CNT1,A ;(1) MOV A,CNT0 ;(1) RRC A ;(1) MOV CNT0,A ;(1) MOV A,CNT1 ;(1) RRC A ;(1) MOV CNT1,A ;(1) MOV A,CNT0 ;(1) RRC A ;(1) MOV CNT0,A ;(1) ; OBS: RESULTADO TOTAL FICOU EM CNT0 (DESPREZAR CNT1, ALTERADO PELO SHIFT) MOV A,CNT0 ;(1) SUBB A,#MIN/80 ;(1) MIN=560 (560/80=7) JNC J032 ;(2) CARRY É NEGATIVO? AJMP RMT_0 ;(2) SIM--HEADER MAIS CURTO DO QUE O MIN. (ERRO.) ; ; ************* VALID HEADER RECEIVED (ESPAÇO EM BRANCO DE 10 TE'S)********************* J032: RCV7: MOV CNT1,#NBITS ; [1] VALID START MARKER WAS RECEIVED MOV CNT2,CNT0 ; [1] CNT2 = CNT0 MOV A,CNT2 ; [1] SEE NOTE BELOW SUBB A,#3H ; [1] MOV CNT2,A AJMP DL1 ; [2] COMPENSATE FOR FIRST BIT ; TOTAL = 32 ;********************************************************************************** ; 2.5 IS AVERAGE PLAY BETWEEN RISING EDGE AND JUMP OUT OF CALIBRATION LOOP. ; 2 FOR JUMP OUT OF RCV3 TO RCV6 ; 11 INSTRUCTIONS FOR RVC6 - CAIBRATION COUNTER DIVIDE ; 8 INSTRUCTIONS FOR RCV7 - COMPENSATE FOR POST CALIBRATION CALCUATIONS ; TOTAL 22.5 INSTRUCTIONS BETWEEN RISING EDGE AND ENTERING DL1 ; THEREFORE SUBTRACT 33/11 = 3 TO COMPENSATE FOR POST CALCULATION ON 1ST BIT ;********************************************************************************** RCV8: ; [1] WAIT A MAXIMUM OF 4 Te MOV TMP_CNT ,#4H ; [1] SET TEMP LOOP COUNTER RCV10A: ; [1] and CSR processing MOV CNT2,CNT0 ; [1] Refer to explanation above RCV10B: ;loop de 11 us x cnt0 nop nop nop SETB PORTA.RFIN ;(1)LEVANTA PARA LEITURA JNB PORTA.RFIN ,J033 ;(2)Wait for rising edge AJMP RCV11 ;(2) RFIN=1 Edge found--Process J033: SETB PORTA.RFIN ;(1)LEVANTA PARA LEITURA JNB PORTA.RFIN , J034 ;(2) Wait for Next rising edge AJMP RCV11 ;(2) RFIN=1 Edge found--Process J034: DJNZ CNT2 , RCV10B ;(2) Decrement Timeout counter ; [2] Loop Back ; TOTAL = 8, RFIN CHECKED EVERY 4uS ON AVERAGE J035: DJNZ TMP_CNT , RCV10A ; [1] ALL Te PERIODS ; [2] ... NO, THEN WAIT FOR NEXT ONE J036: AJMP RMT01 ; [0] ... YES, [0] TIMEOUT--no edge found RCV11: MOV A,CNT0 ; [1] SEE NOTE BELOW SUBB A,#1H ; [1] MOV CNT2,A ; [1] ;************************************************************************* ; 2 SETUP OF TEMP LOOP COUNTER ( ONLY ONCE ) ; 2 SETUP TE LOOP COUNTER ( MAX 4 ) ; 3 DECREMENT TEMP LOOP COUNTER ( MAX 4 ) ; 4 IS THE AVERAGE PLAY BETWEEN EDGE AND EDJE BEING DETECTED IN RCV9 ; 2 JUMP OUT OF RCV10B TO RCV11 ; 3 FOR RCV11 ; TOTAL 10 INSTRUCTIONS BETWEEN EDGE AND ENTERING DL1 ; THEREFORE SUBTRACT 10/11 = 1 => 1 DL1 LOOPS TO COMPENSATE FOR ;************************************************************************* DL1: ;AJMP $+2 ; [2] WASTE TIME xxxxxxxxxxxxxxxxx AJMP $+2 ; [2] WASTE TIME DJNZ CNT2 ,DL1 ; [1] [2, IF SKIP] ; [2] CNT0 X 4 us SAMPLE1: SETB PORTA.RFIN ;LEVANTA PARA LEITURA JB PORTA.RFIN ,J038 ; [2] INPUT HIGH? FIRST SAMPLE AJMP RMT01 ; [0] NO--ERROR J038: ; [1] CALIBRATION COUNTER MOV CNT2,CNT0 ; [1] (NOMINALLY 75 FOR 300 us PULSE) DEC CNT2 ; [1] SUBTRACT 2 FROM FINAL CALIB COUNTER TO COMPENsATE FOR THIS AJMP $+2 ; [2] NOP ; [1] ; TOTAL = 8 => 1 LOOP COUNTER DL2: ajmp $+2 ajmp $+2 AJMP $+2 ; [2] WASTE TIME AJMP $+2 ; [2] WASTE TIME DJNZ CNT2 ,DL2 ; [1] SAMPLE2: MOV TEMP,FLAGS ;NÃO ACESSIVEL A NIVEL DE BIT CLR TEMP.BITIN ; [1] CLEAR BIT POSITION MOV FLAGS,TEMP SETB PORTA.RFIN ;LEVANTA PARA LEITURA JB PORTA.RFIN ,J040 ; [1.5] LEAVE 0 IF LINE HIGH MOV TEMP,FLAGS SETB TEMP.BITIN ; [0.5] MAKE 1 IF LINE LOW MOV FLAGS,TEMP ; SUB TOTAL = 3 CYCLES J040: ACALL ROT_SHIFT ; [11]+[2] CSR SHIFT + CALL MOV TEMP,CSR7 CLR TEMP.7 ; [1] MOV CSR7,TEMP MOV TEMP,FLAGS JNB TEMP.BITIN ,J041 ; [1.5] MOV TEMP,CSR7 SETB TEMP.7 ; [0.5] MOV CSR7,TEMP ; SUB TOTAL = 16 CYCLES J041: ; [1] CALIBRATION COUNTER MOV CNT2 ,CNT0 ; [1] (NOMINALLY 75 FOR 300 us PULSE) MOV A,CNT2 ; [1] SEE CALCULATION BELOW SUBB A,#3 ; [1] MOV CNT2,A NOP ; [1] ; SUB TOTAL = 5 CYCLE ; TOTAL = 38 => 38/11 = 3 LOOP COUNTERS ;************************************************************************* ; TOTAL = 38 INSTRUCTIONS ; SUBTRACT 38/11 = 3 TO COMPESATE FOR UPDATEING CSR AND OTHER PROCESSING ; AFTER DATA SAMPLE IS TAKEN. ;************************************************************************* DL3: AJMP $+2 ; [2] WASTE TIME AJMP $+2 ; [2] WASTE TIME AJMP $+2 AJMP $+2 DJNZ CNT2,DL3 ; [1] CNT0 X 11 US SAMPLE3: SETB PORTA.RFIN ;LEVANTA PARA LEITURA JB PORTA.RFIN ,RMT0 ; [2] INPUT HIGH? THIRD SAMPLE ; [0] YES--RECEIVE ERROR ACALL TST_RTCC ; [11] CHECK RTCC DJNZ CNT1, RCV8A ; [1] LAST BIT? ; [2] ... NO, GET NEXT BIT AJMP RMT1 ; TOTAL = 14 CYCLES RCV8A: AJMP RCV8 ;AUXILIAR DE JUMP LONGO RMT_0: RMT0: RMT01: SETB C ; SETA C MOV A,#1H RET ; RETURN RMT1: ; [2] CNT0 X 8 us [ CNT0 x Te ] SETB PORTA.LED ; VALID TRANSMISSION FORMAT, LED ON MOV A,#0FH ; FORCE OPEN BUTTON CODES TO ZERO ANL A,SER_0 MOV SER_0,A CLR C MOV A,#0H ; VALID SERIAL NUMBER => VALID TX RET ; RETURN ;------------------------------------------------------------------------------ ; ; FUNCTION : M_LOOP () ; ; DESCRIPTION : MAIN PROGRAM ROUTINE ; ;------------------------------------------------------------------------------ M_LOOP: CLR PORTA.LED ;APAGA LED SETB PORTA.LRN ;LEVANTA PARA TESTAR JB PORTA.LRN , J045 AJMP LEARN ; TEST & HANDLE LEARN BUTTON J045: ACALL TST_RTCC ; UPDATE TIMER ACALL TST_TIMER ; HANDLE TIMER - UPDATE OUTPUTS ACALL RECEIVE ; RECEIVE TRANSMISSION JC M_LOOPY ; CHECK IF TRANSMISSION VALID, SE C=1 NÃO VALIDO (ERRO) AJMP M_SEARCH M_LOOPY: AJMP M_LOOP ;AUXILIAR DE JUMP LONGO M_SEARCH: MOV A,#0H MOV TXNUM,A ; TEST FIRST POSITION ; ******* COMPARE LOWER WORD OF SERIAL NUMBER ******** M_SERIAL: ACALL TX_LOOKUP ; GET TX BASE ADDRESS ;SETB ADDRESS.1 ; ADD 2 TO BASE ADDRESS SETB ADDRESS.2 ; ADD 4 TO BASE ADDRESS ACALL EEREAD ; READ LOWER 16-BITS OF SER# FROM EEPROM MOV A,TMP1 ; COMPARE RX AND EEPROM VALUES XRL A,SER_2 JNZ M_NEXT ; IF NOT EQUAL CHECK NEXT MOV A,TMP2 ; COMPARE RX AND EEPROM VALUES XRL A,SER_3 JNZ M_NEXT ; IF NOT EQUAL CHECK NEXT ; ******* COMPARE UPPER WORD OF SERIAL NUMBER ******** M_SERIAL2: INC ADDRESS ; POINT TO NEXT ENTRY ACALL EEREAD ; READ UPPER 16-BITS OF SER# FROM EEPROM MOV A,TMP1 ; COMPARE RX AND EEPROM VALUES XRL A,SER_0 JNZ M_NEXT ; IF NOT EQUAL CHECK NEXT MOV A,TMP2 ; COMPARE RX AND EEPROM VALUES XRL A,SER_1 JNZ M_NEXT ; IF NOT EQUAL CHECK NEXT MOV TEMP,FLAGS JB TEMP.LRNF , J046 ; LEARN MODE AJMP M_HOP ; FOUND TRANSMITTER - DECRYPT J046: MOV TEMP,FLAGS SETB TEMP.RELEARN ; SET RELEARN FLAG MOV FLAGS,TEMP AJMP LEARN_F ; FOUND TRANSMITTER - LEARN ; **** SEARCH NEXT POSITION FOR SERIAL NUMBER ***** M_NEXT: INC TXNUM ; POINT TO NEXT TRANSMITTER POSITION ; MOV A,TXNUM SUBB A,#MAX_USERS JNC J047 ; NOT FOUND IN MAP AJMP M_SERIAL J047: ; TRY NEXT POSITION M_NF: MOV TEMP,FLAGS JB TEMP.LRNF ,J048 ; LEARN MODE AJMP M_LOOP ; NO... INVALID SERIAL NUMBER J048: AJMP LEARN_NF ; NEW TRANSMITTER - USE POINTER FOR LEARN ; ********** DECRYPT HOPCODE ********************* M_HOP: ACALL DECRYPT ; DECRYPT HOPCODE ; ********* TEST DICRIMINATION VALUE ************* M_DIS: MOV A,SER_3 ; SERIAL NUBER LSB MUST BE EQUAL XRL A,DISC ; TO DISCRIMINATION VALUE JNZ M_LOOPx1 AJMP xx1 M_LOOPx1: AJMP M_LOOP ;AUXILIAR DE JUMP LONGO ; *************** CHECK COUNTERS VALID ************ xx1: MOV TEMP,FLAGS CLR TEMP.SEC_CNT ; CHECK FIRST COUNTER MOV FLAGS,TEMP M_CNT: ACALL TX_LOOKUP ; POINT LOWER 16 BIT COUNTER MOV TEMP,FLAGS JNB TEMP.SEC_CNT ,J049 ; IF SECOND COUNTER IS USED INC ADDRESS ; INCREMENT ADDRESS J049: ACALL EEREAD ; READ LOWER 16 BIT COUNTER FROM EEPROM ; ************ CHECK COUNTER WINDOWS *********** M_SUB: MOV A,CNTR_LW ; 16 BIT COUNTER SUBSTRACTION SUBB A,TMP2 MOV TMP2,A JC J050 ; SKIP IF NO BORROW INC TMP1 ; ... ELSE INCR HI BYTE J050: MOV A,CNTR_HI SUBB A,TMP1 MOV TMP1,A MOV TEMP,TMP1 CLR TEMP.0 ; MAKE ACCEPTED WINDOW 512 MOV TMP1,TEMP M_CHECK0: MOV A,TMP1 ; TEST IF IN WINDOW ( UPPER BYTE ) JZ J051 AJMP M_CHECK2 ; GO AND CHECK LOWER BYTE J051: MOV TEMP,FLAGS JNB TEMP.SEC_CNT,J052 ; IF SECOND COUNTER AJMP M_LOOP ; ERROR - GOTO MAIN LOOP J052: MOV TEMP,FLAGS SETB TEMP.SEC_CNT ; SET FLAG FOR SECOND COUNTER CHECK MOV FLAGS,TEMP AJMP M_CNT ; AND CHECK IT M_CHECK2: MOV A,TMP2 ; CHECK LOWER BYTE JZ M_TZERO ; IF REPEAT - RESET TIMEOUT COUNTER ; ************ UPDATE EEPROM COUNTER *********** M_UPDATE: ACALL TX_LOOKUP ; GET CURRENT TX BASE ADDRESS ACALL LOAD_CNT_VALS ; LOAD COUNTER VALUES ACALL EEWRITE ; UPDATE FIRST COUNTER ACALL LOAD_CNT_VALS ; LOAD COUNTER VALUES ACALL EEWRITE ; UPDATE SECOND COUNTER ; ******** UPDATE OUTPUT WITH CURRENT BUTTON CODE ******** M_OUTPUT: M_OUTPUT1: mov c, func.7 ; CHANGE BUTTON TO S-OUTPUT FORMAT mov portb.2,c mov c, func.6 ; [ S2 S1 S0 S3 ] mov portb.1,c mov c, func.5 mov portb.0,c mov c, func.4 mov portb.3,c M_TZERO: MOV A,#0H MOV CNT_HI,A ; RESET RTCC CLOCK MOV CNT_LW,A M_END: AJMP M_LOOP ; WAIT FOR NEXT TRANMISSION ;------------------------------------------------------------------------------ ; ; FUNCTION : LEARN () ; ; DESCRIPTION : LEARN ROUTINE ; ;------------------------------------------------------------------------------ LEARN: MOV A,#0H MOV CNT_LW,A MOV CNT_HI,A ; RESET TIMER LEARN1: SETB PORTA.LED ; LED ON ACALL TST_RTCC ; UPDATE TIMER SETB PORTA.LRN ;LEVANTA PARA TESTAR JNB PORTA.LRN ,J054 ; TEST FOR BUTTON RELEASE AJMP LEARN2 ; ENTER LEARN MODE J054: JB CNT_HI.0 , J055 ; TEST FOR ERASE ALL AJMP LEARN1 ; LOOP BACK ; ******* EEPROM ERASE ALL ****************** J055: CLR PORTA.LED ERASE_ALL: SETB PORTA.LRN ;LEVANTA PARA TESTAR JB PORTA.LRN , J056 ; WAIT FOR BUTTON RELEASE AJMP ERASE_ALL ; LOOP BACK J056: ; ERASE ENABLE COMMAND ACALL EEERASE ; ERASE ALL DATA OF MEMORY AJMP RESETA ; START OVER LEARN2: CLR PORTA.LED ; CLEAR LED MOV TEMP,FLAGS SETB TEMP.LRNF ; SET LEARN FLAG MOV FLAGS,TEMP LEARN3: ACALL TST_RTCC ; UPDATE TIMER ACALL TST_TIMER ; CHECK FOR LEARN TIMEOUT ACALL RECEIVE ; RECEIVE TRANSMISSION JC LEARN3 ; CHECK IF TRANSMISSION VALID AJMP M_SEARCH ; CHECK IF SERIAL NUMBER IS IN MAP LEARN_NF: ; *** IF SERIAL NOT IN MAP READ SELFLEARN POINTER *** ; POINT TO LEARN POINTER MOV ADDRESS,#LRNPTR ACALL EEREAD ; READ LEARN POINTER FROM EEPROM MOV A,TMP2 ; CHECK LOWER BYTE JNZ J057 ; IF LOWER != 0 LEARN ON 0 MOV TXNUM,TMP1 ; ELSE LEARN ON TMP1 VALUE AJMP LEARN_F J057: MOV TXNUM,#0H ; LOAD TXNUM LEARN_F: ACALL TX_LOOKUP ;SETB ADDRESS.1 ; ADD 2 TO BASE ADDRESS SETB ADDRESS.2 ; ADD 4 TO BASE ADDRESS ; GET LOWER 16 BIT OF SERIAL NUMBER MOV TMP1,SER_2 MOV TMP2,SER_3 ACALL EEWRITE ; ... AND WRITE TO EEPROM ; GET UPPER 16 BIT OF SERIAL NUMBER MOV TMP1,SER_0 MOV TMP2,SER_1 ACALL EEWRITE ; ... AND WRITE TO EEPROM ; *** DECRYPT HOP CODE *** LEARN_DEC: ACALL DECRYPT ; DECRYPTION ROUTINE ; *** CHECK DISCRIMINATION VALUE *** LEARN_CHK: MOV A,SER_3 ; CHECK LOWER BYTE OF SERIAL NUMBER XRL A,DISC ; AGAINST DISCRIMINATION VALUE JZ LEARN_UP ; UPDATE LEARN POINTER AJMP CANCEL_LEARN ; ERROR CANCEL LEARN MODE ; ********* UPDATE LEARN POINTER ********** LEARN_UP: ACALL TX_LOOKUP ; GET CURRENT TX BASE ADDRESS ACALL LOAD_CNT_VALS ACALL EEWRITE ; WRITE LSB WORD OF COUNTER TO EEPROM MOV TEMP,FLAGS JNB TEMP.RELEARN ,J058 ;IF RELEARN AJMP BYPASS_POINTER_WRITE ; DONT UPDATE POINTER J058: INC TXNUM ; INCREMENT LEARN POINTER clr c MOV A,TXNUM ; ALLOW 0 .. MAX_USERS - 1 SUBB A,#MAX_USERS ; IF MAX WRAP TO 0 JNC J059 MOV TMP1,TXNUM ; ELSE USE TXNUM AJMP PP J059: MOV TMP1,#0H ; FOR WRITE OPERATION PP: MOV TMP2,#0H ; CLEAR LOWER BYTE MOV ADDRESS,#LRNPTR ; POINT TO LEARN POINTER ACALL EEWRITE ; UPDATE LEARN POINTER IN EEPROM BYPASS_POINTER_WRITE: SETB PORTA.LED ; LED ON TO INDICATE VALID LEARN MOV CNT_LW,#0H ; CLEAR COUNTER LOW BYTE SUCCESS: ACALL TST_RTCC ; INDICATE SUCCESSFUL LEARN JB CNT_LW.4 , J060 ; LED ON FOR 0.5 SEC AJMP SUCCESS ; LOOP BACK J060: CANCEL_LEARN: MOV TEMP,FLAGS CLR TEMP.LRNF ; CLEAR LEARN FLAG CLR TEMP.RELEARN ; CLEAR RELEARN FLAG MOV FLAGS,TEMP AJMP M_LOOP ; RETURN TO MAIN LOOP - LED OFF ;------------------------------------------------------------------------------ ; END OF FILE : SIMDEC10.ASM ;------------------------------------------------------------------------------ END