;********************************************************************* ;* * ;* Décodage de télécommande IR RC5 (PHILIPS) * ;* * ;* par J. Weiss, Service Electronique * ;* SUPÉLEC Campus de Rennes, France * ;********************************************************************* ; ; PRÉSENTATION DU PROGRAMME ; ; Ce programme tourne sur un PIC16C84. ; ; Description de la carte ; ; AFFICHAGE ; L'affichage se fait sur 4 afficheurs LED 7 segments sous la forme : ; ; ( 88:88 ) ; ; Les mêmes segments des 4 afficheurs sont tous reliés entre eux et sont ; connectés au port B (a=RB1 ; b=RB2 ; c=RB3 ; d=RB4 ; e=RB5 ; f=RB6 ; g=RB7); ; ; Les ":" sont réalisés par les virgules des 2 afficheurs du milieu (celui de ; droite est retourné) qui sont connectées au bit 0 du port B. ; ; Les afficheurs sont de type anode commune (HPDSP7511) et leurs anode est ; connectée au port A (digit0=RA3 ; digit1=RA2 ; digit2=RA1 ; digit3=RA0). ; ; ; PRINCIPE DU DÉCODAGE RC5 : ; ATTENTE : à l'initialisation, on vérifie que le senseur IR est inactif ; (RA4 = 1); on se place alors dans l'attente d'un front descendant de ; RA4 (indiquant un signal) tout en effectuant un cycle d'affichage. ; ; Une fois un signal détecté, on initialise le timer de façon à lire ; l'état du senseur à chaque bit du code RC5; on maintien cela jusqu'à ; l'obtention de tous les bits du code (13) sauf si on ne constate aucune ; transition entre 2 tops du timer (cas d'erreur). ; ; si tout c'est bien passé (enregistrement des 13 bits), on valide le code ; et on passe en mode d'attente/affichage. ; ; L'oscillateur à quartz utilisé génère une fréquence de 1,8432 MHz, cela ; donne une fréquence interne de 460,8 kHz (T= 2,17 µs); une prédivision ; par 4 du timer donne un comptage de 205 cycles pour la durée d'un bit ; du code RC5(1,778 ms). ; ; FONCTIONNALITÉS DU PROGRAMME : ; ; le programme décode toutes les touches de la télécommande et affiche : ; l'adresse (0 : TV ou 4 : VCR) sur le digit3 (à gauche) ; le bit de répétition sur le digit2 (tiret milieu ou bas) ; le code : en hexadécimal s'il s'agit d'une fonction ; en décimal s'il s'agit d'une valeur numérique. ; ; si le code précédemment reçu était numérique, les touches + et - ; permettent d'incrémenter ou de décrémenter la valeur. ; ; le programme comprend 225 lignes de code et nécessite 14 octets de RAM ;************************** Déclarations ************************* ; ; Programme : rem_RC5.ASM ; Révision : V 1.00 mars 96 ; Auteur : Jacques.Weiss@supelec.fr LIST P = 16C84 LIST F = INHX8M __config H'3F1A' ; CP : off,PWRTE : on, WDT : off, HS OSC INCLUDE "PIC84JW.H" ;************************** Déclarations ************************* ; ;PORT_A equ H'05' ; anodes communes des afficheurs 7 segments ;PORT_B equ H'06' ; segments et virgules des afficheurs et interrupteurs ; ZEROT equ H'81' UN equ H'F3' DEUX equ H'49' TROIS equ H'61' QUATRE equ H'33' CINQ equ H'25' SIX equ H'05' ; Table des segments (PORT_B) SEPT equ H'F1' HUIT equ H'01' NEUF equ H'31' A_HEX equ H'11' B_HEX equ H'07' C_HEX equ H'8D' D_HEX equ H'43' E_HEX equ H'0D' F_HEX equ H'1D' BLANC equ H'FF' TIRET_H equ H'BF' TIRET_M equ H'7F' TIRET_B equ H'EF' POINT equ H'FE' ; Constantes pour le comptage du timer C_RC5 equ B'00000001' ; configuration du timer (1:4) T_RC5 equ D'55' ; longueur de cycle de 1,778 ms (255-205) ; ; VARIABLES org RAM affiche res 1 ; quel afficheur raffraîchir ? digit0 res 1 ; Digit des minutes (à droite) digit1 res 1 ; Digit des dizaines de minutes digit2 res 1 ; Digit des heures digit3 res 1 ; Digit des dizaines de heure marque res 1 ; type de code (marque) tempo res 1 ; variable temporaire tempo2 res 1 ; variable temporaire curseur res 1 ; stockage de la position code res 2 ; code reçu final res 1 ; code validé a_final res 1 ; adresse finale count res 1 ; Variable de comptage ; ;******************************************************************************** ORG PIC84 GOTO START ;******************************************************************************** ; retour d'interruption du timer org RETOUR_INT movlw B'10000000' ; INTCON : GIE=1 ; EEIE=0 ; TOIE=0 ; INTE=0; flags à 0 movwf INTCON ; Positionnement des int et des flags RETFIE ;******************************************************************************** ; Initialisation des ports et effacement de l'affichage START movlw C_RC5 ; T0CS=0 ; T0SE=x ; PSA=0 ; PS[2:0]=1 call CONFIG_TIMER ; Règlage du timer RTCC (1:4) sur horloge interne BSF STATUS,RP0 ; Passage au banc mémoire 1 movlw B'10000000' ; INTCON : GIE=1 ; EEIE=0 ; TOIE=0 ; INTE=0; flags à 0 movwf INTCON ; Positionnement des int et des flags movlw B'10000' movwf TRISA ; Tous les bits du port A en sortie (sauf RA4) clrf TRISB ; Tous les bits du port B en sortie BCF STATUS,RP0 ; Retour au banc mémoire 0 movlw BLANC movwf PORT_B ; On n'affiche rien movlw H'0F' ; tempo d'affichage movwf count ; ; initialisation des variables clrf code ; on initialise le code à 0 clrf affiche ; on initialise l'afficheur (rien) clrf a_final ; on initialise l'adresse clrf final ; on efface le code final clrf digit0 ; on efface le digit0 clrf digit1 ; on efface le digit1 movlw TIRET_M movwf digit2 ; on met un tiret sur le digit2 clrf digit3 ; on efface le digit3 ;******************************************************************************** MAIN movlw H'FF' movwf tempo movlw H'3F' movwf tempo2 MAIN2 decf tempo,F ; temporisation pour gérer les bnz MAIN3 ; frappes numériques multiples decf tempo2,F ; de 0 à 99 skpnz bcf a_final,7 MAIN3 call CODE_RC5 ; RA4 est à 0, on démarre movlw D'14' ; on a 13 bits à lire (trame RC5) subwf curseur,W bnz MAIN CALL AFFICHAGE ; on lance l'affichage goto MAIN2 ;******************************************************************************** CODE_RC5 movlw D'14' ; on a 13 bits à lire (trame RC5) movwf curseur ; curseur sert à se positionner dans la trame btfss PORT_A,4 ; RA4 est-il actif (à 0) goto INIT_RC5 ; RA4 est à 0, on démarre return ; non, on retourne au programme principal INIT_RC5 movlw B'00000001' ; T0CS=0 ; T0SE=x ; PSA=0 ; PS[2:0]=1 call CONFIG_TIMER ; Règlage du timer RTCC (1:4) sur horloge interne movlw T_RC5 ; initialisation du timer movwf RTCC ; initialisation du timer movlw 7 movwf marque ; on initialise la marque à une valeur bidon bsf INTCON,T0IE ; on valide le timer ATTENTE_TIMER btfss PORT_A,4 ; on vérifie qu'il y a un créneau clrf marque ; si oui, on efface la marque btfsc INTCON,T0IE ; on boucle en attente d'une interruption goto ATTENTE_TIMER TSTF marque ; y a-t'il eu créneau ? bz EXTRACT ; non alors il y a eu erreur return EXTRACT clrc ; on présume un "0" btfss PORT_A,4 ; vérification setc ; eh non, c'est un "1" rlf code,F ; on enregistre le bit dans le code (LSB) rlf code+1,F ; on enregistre le bit dans le code (MSB) decfsz curseur,F ; on a tous les bits ? goto INIT_RC5 ; non, alors on boucle VALID_C rlf code,W ; on dispose du code et de l'adresse : rlf code+1,F ; code+1 code rlf code,W ; 0,0,0,0,REP,A4,A3,A2 A1,A0,S5,S4,S3,S2,S1,S0 rlf code+1,F ; on récupère l'adresse dans code+1 bcf code+1,7 ; le bit 7 va servir à identifier une frappe numérique bcf code+1,6 ; le bit 6 va servir à indiquer un affichage décimal movlw TIRET_M btfsc code+1,5 ; si le bit REP est à 1, movlw TIRET_B ; on l'indique dans digit2 movwf digit2 movfw code ; on enregistre le bit andlw H'3F' ; masquage des bits inutiles (code sur 6 bits) movwf code movfw code+1 ; on test le bit de répétition xorwf a_final,W ; par rapport au coup précédent andlw H'20' ; isolation du bit 5 (bit de répétition) bz FIN_RC5 ; la touche n'a pas été relachée FRAPPE_MULTIPLE movlw D'10' ; on teste le code pour savoir s'il s'agit subwf code,w ; des touches numériques bnc FRAP1 movfw a_final ; test si le code précédent était numérique andlw H'C0' bz FIN_FRAPPE ; non movlw H'20' ; est-ce la touche '+' subwf code,W movlw 1 bz PLUS_MOINS movf final,F bz FIN_RC5 ; le code est déja à 0 movlw H'21' ; est-ce la touche '-' subwf code,w movlw -1 bz PLUS_MOINS goto FIN_FRAPPE PLUS_MOINS addwf final,W ; on incrémente ou on décrémente le code final movwf code ; on enregistre la nouvelle valeur bsf code+1,6 ; il s'agit d'une valeur numérique goto FRAP3 FRAP1 ; le code correspond aux chiffres (0 à 9) bsf code+1,7 ; on indique dans les poids forts de code+1 bsf code+1,6 ; qu'il s'agit d'une frappe numérique btfss a_final,7 ; test si le code précédent était numérique goto FIN_FRAPPE ; non movfw final ; oui, alors on multiplie la valeur précédente par 10 clrc ; on évite de propager une éventuelle retenue précédente rlf final,F ; multiplication par 2 rlf final,F ; multiplication par 2 (soit *4) rlf final,F ; multiplication par 2 (soit *8) addwf final,F ; plus une fois (soit *9) addwf final,W ; plus une fois, résultat dans w addwf code,F ; ajout du code courant FRAP3 movlw D'100' ; la valeur max autorisée est de 99 subwf code,W bc FIN_RC5 bcf code+1,7 ; on efface le bit 7 pour afficher 2 digits ; bsf code+1,6 ; bit d'état pour affichage décimal FIN_FRAPPE movfw code movwf final ; on enregistre le code movfw code+1 movwf a_final ; on enregistre l'adresse FIN_RC5 return ;******************************************************************************** AFFICHAGE decfsz count,F ; on n'affiche qu'un coup sur 128 return movlw H'7F' movwf count movfw final btfsc a_final,6 ; test du bit d'état pour affichage décimal call BIN_BCD call RENVOI_CODE ; Recherche du code dans la table des segments movwf digit0 swapf final,W btfsc a_final,6 ; test du bit d'état pour affichage décimal movfw digit1 call RENVOI_CODE ; Recherche du code dans la table des segments movwf digit1 movfw a_final call RENVOI_CODE ; Recherche du code dans la table des segments movwf digit3 ; le digit3 donne le code de la marque AFFICHE_7SEG btfsc affiche,0 goto AFF0 btfsc affiche,1 goto AFF1 btfsc affiche,2 goto AFF2 btfsc affiche,3 goto AFF3 movlw 1 movwf affiche return AFF0 movfw digit0 ; on digit0 place dans w movwf PORT_B ; on envoie w vers les afficheurs (Port B) movlw 8 ; Cycle d'affichage du digit concerné movwf PORT_A ; Validation de l'affichage movlw 2 movwf affiche return AFF1 movlw BLANC btfss a_final,7 ; on est en mode numérique (premier digit) movfw digit1 ; on digit1 place dans w movwf PORT_B ; on envoie w vers les afficheurs (Port B) movlw 4 ; Cycle d'affichage du digit concerné movwf PORT_A ; Validation de l'affichage movwf affiche return AFF2 movfw digit2 ; on digit2 place dans w movwf PORT_B ; on envoie w vers les afficheurs (Port B) movlw 2 ; Cycle d'affichage du digit concerné movwf PORT_A ; Validation de l'affichage movlw 8 movwf affiche return AFF3 movfw digit3 ; on digit3 place dans w movwf PORT_B ; on envoie w vers les afficheurs (Port B) movlw 1 ; Cycle d'affichage du digit concerné movwf PORT_A ; Validation de l'affichage movwf affiche return ;******************************************************************************** CONFIG_TIMER BSF STATUS,RP0 ; Passage au banc mémoire 1 ; w : T0CS,T0SE,PSA=0, PS[2:0] movwf OPT ; Règlage du timer RTCC sur horloge interne BCF STATUS,RP0 ; Retour au banc mémoire 0 return ;******************************************************************************** BIN_BCD movwf digit0 ; on enregistre l'octet dans digit0 clrf digit1 gtenth movlw D'10' ; on effectue la division par subwf digit0,W ; soustractions successives bnc FIN_BIN movwf digit0 incf digit1,F goto gtenth FIN_BIN movfw digit0 return ;******************************************************************************** RENVOI_CODE andlw H'0F' ; la table ne contient que 16 entrées addwf PC,F retlw ZEROT retlw UN retlw DEUX retlw TROIS retlw QUATRE retlw CINQ retlw SIX retlw SEPT retlw HUIT retlw NEUF retlw A_HEX retlw B_HEX retlw C_HEX retlw D_HEX retlw E_HEX retlw F_HEX END