;****************************************************************************************** ; RX_GEN_51_NOHOP.ASM ; FUNÇÃO: RECEBER SINAL DE UM HCS200/201/300/301 SEM USAR SISTEMA HOPPING CODE ; ACIONANDO SAIDAS TEMPORIZADAS NO AT89C2051. ; NESTA MONTAGEM, NÃO NECESSITA DE 'CHAVE' DE ENCRIPTAÇÃO, USANDO SOMENTE O ; NUMERO SERIAL DO CONTROLE E A INFORMAÇÃO DOS BOTÕES APERTADOS. ; QUALQUER CONTROLE COMERCIAL, USANDO HCS200..301, DE QUALQUER FABRICANTE, ; OPERANDO A 400US DE TE, DEVERÁ FUNCIONAR E SER 'APRENDIDO'. ; BLOG 'LARIOS.TECNOLOGIA.WS' ; 15/08/2012 - ADAPTADO POR CLÁUDIO LÁRIOS - BASEADO EM 'NOTES APPLICATION MICROCHIP' ; GRAVAR CONTROLE: APERTE UM BOTÃO DO CONTROLE E MANTENHA APERTADO. ; APERTE TAMBÉM O BOTÃO 'LEARN' NA PLACA (PINO 4 DO PIC 12F629 A MASSA)E ; SOLTE-O EM MENOS DE 1 SEGUNDOS. O LED 'LEARN'(PINO 2) PISCARÁ 1 ; VEZ, PARA INDICAR 'CODE APRENDIDO'. REPITA ISTO COM TODOS OS CONTROLES REMOTOS QUE ; FOR UTILIZAR, UM POR VEZ. ; APAGAR TODOS OS CONTROLES DA MEMÓRIA: APERTAR BOTÃO 'LEARN' NA PLACA E ; MANTENHA PRESSIONADO POR MAIS DE 10 SEGUNDOS. O LED 'LEARN' (PINO 2) PISCARÁ ; 3 VEZES , INDICANDO O PLENO APAGAMENTO DE TODOS OS SENSORES DA MEMÓRIA. ; APÓS ISTO, CADA CONTROLE DEVERÁ SER 'REAPRENDIDO' NOVAMENTE PARA OPERAR. ; QUANTIDADE MÁXIMA DE CONTROLES: 30 CONTROLES COM CI HCS 200..301. ; (NÃO USA HOPPING CODE, APENAS O NÚMERO FIXO DO SERIAL NUMBER). ;*************************************************************************** ;------------------------------------------------------------------------------ ; Utiliza uma memória 24c02 OU 24C04 (METADE) para armazenar dados dos códigos dos ; transmissores permitidos. ; PINAGENS AT89C2051: ; 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) ; RAM TEMP EQU 20H FLAGS EQU 39H ; USER FLAG REGISTER ADDRESS EQU 21H ; ADDRESS REGISTER TXNUM EQU 32H ; CURRENT TX OUTBYT EQU 23H ; GENERAL DATA REGISTER MASK EQU OUTBYT ; MASK REGISTER USED IN DECRYPTION TMP_CNT EQU OUTBYT ; TEMPORARY COUNTER ; COUNTER REGISTERS BYTE_SW EQU 26H CNT0 EQU 24H ; LOOP COUNTERS CNT1 EQU 25H CNT2 EQU 51H AUX3 EQU 52H 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 CSR4 EQU 2DH CSR5 EQU 2EH CSR6 EQU 2FH CSR7 EQU 30H 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 SER_0 EQU CSR7 ; 28 BIT SERIAL NUMBER SER_1 EQU CSR6 SER_2 EQU CSR5 SER_3 EQU CSR4 CNTR_HI EQU 2AH CNTR_LW EQU 29H ; ********* 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 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 BYTE_SW,#0H MOV FLAGS,#0H ;CLRF FLAGS; RESET FLAGS AJMP M_LOOP ; GOTO MAIN PROGRAM LOOP ;+============================================================================ ; SUB-ROTINAS GERAIS: ;============================================================================= 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 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 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 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 ;MULTIPLICA POR 4 ;RLC A ; MULTIPLY BY 8 MOV ADDRESS,A RET 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 ; **** INCREMENTA 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 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 LOAD_CNT_VALS: MOV TMP1,CNTR_HI ; LOAD MSB OF COUNTER MOV TMP2,CNTR_LW ; LOAD LSB OF COUNTER RET RECEIVE: ;******** ESPERA PELO CABEÇALHO E CALIBRA******************* 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 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.) ; ; ************* RECIBIDO CABEÇALHO VÁLIDO (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 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] 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 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: MOV BYTE_SW,SER_0 ;SALVA BOTÕES ; [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 ;------------------------------------------------------------------------------ ; ; : ROTINA PRINCIPAL ; ;------------------------------------------------------------------------------ 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 M_HOP: ; ******** UPDATE OUTPUT WITH CURRENT BUTTON CODE ******** M_OUTPUT: M_OUTPUT1: mov c, BYTE_SW.7 ; CHANGE BUTTON TO S-OUTPUT FORMAT mov portb.2,c mov c, BYTE_SW.6 ; [ S2 S1 S0 S3 ] mov portb.1,c mov c, BYTE_SW.5 mov portb.0,c mov c, BYTE_SW.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 J056: ; ERASE ENABLE COMMAND ACALL EEERASE ; ERASE ALL DATA OF MEMORY MOV AUX3,#8H ;PISCA LED 'LEARN' PARA INDICAR SUCESSO NO APAGAMENTO VHJ1: MOV CNT_LW,#0H ;LIMPA CONTADOR DE TEMPO JB PORTA.LED,AP_LED SETB PORTA.LED ;LIGA LED "LEARN' GHJ1: ACALL TST_RTCC JNB CNT_LW.3,GHJ1 DJNZ AUX3,VHJ1 CLR PORTA.LED AJMP X43 AP_LED: CLR PORTA.LED AJMP GHJ1 X43: SETB PORTA.LRN ;LEVANTA PARA TESTAR JNB PORTA.LRN ,X43 ; AGUARDA SOLTAR BOTÃO 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 LEARN_DEC: LEARN_UP: 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