; MM53200 decoder emulation with a PIC12C508 ; Origine DA nov 2001 pour accepter 2 bits variables, ; et envoyer 2 codes compléments si demandé ; une transmission démarre par ; ; un start ___________|¨¨¨¨|_ ; ; puis 12 bits de données (Key1 MSB en premier) ; ; bit à 0 ¨|_____|¨¨¨¨¨¨¨¨|_ pin a la masse sur MM53200 ; bit à 1 ¨|_________|¨¨¨¨|_ pin ouverte sur MM53200 ; ; sequence unitaire start,key1 (8 bits),1,0,b1,b0 pause ; ; Tau = 431 us, Tbit = 3 x tau ; list p=12c508 include __CONFIG _CP_OFF & _WDT_ON & _MCLRE_OFF & _IntRC_OSC __IDLOCS h'DADA' ;----- constants --------------------------------------- bit0 equ 0 ; GP0 IO TTL Input bit 0 of emitted code bit1 equ 1 ; GP1 IO TTL Input bit 1 of emitted code OutMono equ 2 ; GP2 IO ST Output monostable RX equ 3 ; GP3 I TTL Input RX OutBist equ 4 ; GP4 IO TTL Output bistable monocle equ 5 ; GP5 IO TTL Input mode simple (=1) ou double code (=0) Key0 equ 0xDA ; key (8 bits) NbTrans equ 0x4 ; nombre de transmissions ok pour trigger ;----- Local data registers --------------------------- TransCount equ 0x07 BitCount equ 0x08 DelayCount equ 0x09 ;Key0s equ 0x0A ; clé à trouver MSB Key1 equ 0x0B ; clé à trouver LSB GPIObk equ 0x0C ; sauvegarde GPIO avant le dodo Digit0 equ 0x10 ; clé reçue MSB Digit1 equ 0x11 ; clé reçue LSB PKValid equ 0x12 ; nombre de fois que la clé primaire est OK SKValid equ 0x13 ; nombre de fois que la clé secondaire est OK ;#define MPSIM 1 Reset org 0 movfw OSCCAL ; store OSCAL value movlw b'01001010' ; wakeup on change, weak pull-up off option ; prescaler on WDT, rate 1:4 movlw b'11101011' ; Set GP4 as output and the rest are inputs tris GPIO ; xxIOIOII movf GPIObk,w ; restaure GPIO, normallement on en a pas besoin movwf GPIO ; c'est pas sécurité btfsc STATUS,GPWUF call PinChange ; ici il y a eu un pin change sur GP0, GP1, GP3 btfss STATUS,NOT_TO call TimeOut ; ici il y a eu un time out [45;72;120] InitPOR clrf GPIO ; ici c'est la mise sous tension TimeOut KeyErr ; point de retour d'une mauvaise clé BitErr ; point de retour d'une erreur de format clé InitERR bcf GPIO,OutMono clrf PKValid clrf SKValid Dodo movf GPIO,w ; lecture du port - recommandé par Microchip movwf GPIObk ; sauvegarde du port SLEEP ; et on attend un bit change ou un WDT ; org 0x040 ; skip the first 64 locations not protected by code protect ;------------------------------------------------------------------------------- RLDigit rlf Digit1,F ; Cy << Digit0.7 << Digit0.6 ... Digit1.1 << Digit1.0 << Cy rlf Digit0,F retlw 0 ;------------------------------------------------------------------------------- ; wait 1/2 ou 1 slot ; un bit 53200/3750 est fait de 3 slots ; un slot de 53200 dure 32/Fosc, Fosc=2/RC, ; la data sheet 53200 donne une durée bit de 960 us pour 100 kHz ; ici on a une fréquence ~74 kHz avec 100 k et 270 pF, durée slot = ~432 us Wait05Slot IFDEF MPSIM retlw 0 ELSE movlw 0x2A ; delay 1+1+42*5-1+2+2=215 us ENDIF goto Delay Wait1Slot IFDEF MPSIM retlw 0 ELSE movlw 0x55 ; delay 1+1+85*5-1+2+2=430 us ENDIF ;------------------------------------------------------------------------------- ;Delay for 1+W*5-1+2 us with 4MHz oscillator ; maximum for W=0 is 1284 us Delay movwf DelayCount DelayStart: nop nop decfsz DelayCount,F goto DelayStart retlw 0 ;---------------------------------------------------------------------------------- PinChange movf GPIO,w ; W=GPIO xorwf GPIObk,f btfss GPIObk,RX ; Rx change ?? goto InitPOR ; non c'est GP0 ou GP1 qui ont bougé ==> si power up btfss GPIO,RX ; RX=1 ?? goto BitErr ; non ==> bit error clrwdt ; ici on est dans le start bit, RX=1 Decode12b movlw 0x0C movwf BitCount ; 12 bits to receive WaitFor0 btfsc GPIO,RX ; attend la transition 1>0 (3 échantillons à 0) goto WaitFor0 btfsc GPIO,RX goto WaitFor0 btfsc GPIO,RX goto WaitFor0 call Wait05Slot ; attend 1/2 slot, on est sur le slot à 0 btfsc GPIO,RX ; on vérifie qu'il est à 0, 3 fois goto BitErr btfsc GPIO,RX goto BitErr btfsc GPIO,RX goto BitErr call Wait1Slot ; attend 1 slot, on est sur le slot variable bsf STATUS,C ; on echantillone le bit ; carry = RX btfsc GPIO,RX ; si Rx=0, alors Cy=1 bcf STATUS,C call RLDigit ; digit0 << digit 1 << Cy (=Rx bit) call Wait1Slot ; attend 1 slot, on est sur le slot à 1 btfss GPIO,RX ; on vérifie qu'il est à 1, 3 fois goto BitErr btfss GPIO,RX goto BitErr btfss GPIO,RX goto BitErr decfsz BitCount,F ; last bit ? goto WaitFor0 call Wait1Slot ; attend 1 slot, on est sur la pause ; on a reçu une clé valide, ; digit0=xxxxcba8 digit1=76543210 call RLDigit call RLDigit call RLDigit call RLDigit ; digit0=cba87654 digit1=3210xxxx ; compare digit0 et key0 movlw Key0 ; clé a trouver, MSB subwf Digit0,w ; w=digi0-key0 btfss STATUS,Z goto KeyErr movlw 0xF0 ; crabouille les 4 bits poids faible andwf Digit1,f ; initialize key1 received after key0 10xx0000 movlw 0x80 btfsc GPIO,bit0 ; get bit0 iorlw 0x10 ; put it on position 4 btfsc GPIO,bit1 ; get bit1 iorlw 0x20 ; put it on position 5 movwf Key1 ; sauvegarde cette clé ; a ce niveau on a digit0=cba87654 digit1=3210.... ; compare digit1 et key1 movf Key1,w subwf Digit1,w ; w=digi1-key1 btfsc STATUS,Z goto KeyPOK ; compare digit1 et key.xor.C0 ; et fait çà seulement si on est en mode coucle clé (monocle=0) btfsc GPIO,monocle ; test bit monocle, simonocle=1 mono clé goto KeyErr movf Key1,w ; inverse les 2 bits de poids forts de KEY1 xorlw b'11000000' subwf Digit1,w ; w=digi1-key1 btfsc STATUS,Z goto KeySOK goto KeyErr ;------------------------------------------------------------------------------ KeyPOK ; clé primaire reçue ok incf PKValid,f movlw 4 subwf PKValid,w ; W=PKvalid - 4 ; Cy=1 si reg>=4 btfss STATUS,C goto Dodo btfss GPIO,monocle ; test bit monocle, simonocle=1 mono clé goto Dodo goto Click KeySOK ; clé secondaire reçue ok movlw 4 subwf PKValid,w ; W=PKvalid - 4 ; Cy=1 si PKvalid>=4 btfss STATUS,C goto KeyErr ; mais clé primaire pas reçue, dommage -> reset incf SKValid,f movlw 4 subwf SKValid,w ; W=SKvalid - 4 ; Cy=1 si SKvalid>=4 btfss STATUS,C goto Dodo ;------------------------------------------------------------------------------ Click btfsc GPIO,OutMono goto Dodo ; OutMono est déjà à 1, on va se coucher bsf GPIO,OutMono ; c'est le front montant ; complemente OutBist en utilisant des instructions bit plutot qu'un COMF btfsc GPIO,OutBist goto ClearOutBist ; si OutBist=1 alors OutBist=0 SetOutBist bsf GPIO,OutBist goto Dodo ClearOutBist bcf GPIO,OutBist goto Dodo end