;****************** ;* LANC * ;* VERSION * ;* SIMPLE * ;* enregistrement * ;* LINO DE MARTIN * ;* Mai 2004 * ;****************** ;Avec LANC on est bien loin du simple interrupteur pour commander l'enregistrement. ;Ce programme s'inscrit dans une application de caméra embarquée sur un VTT. ;Il sert à réaliser une télécommande extra simple ;uniquement pour lancer et arrêter l'enregistrement en mode VCR ;pour mon caméscope (Sony trv33) selon le protocole LANC. ;Elle devrait fonctionner avec tous les autres caméscopes utilisant ce protocole ;mais je ne l'ai pas vérifié, à vous de jouer. ;**************** ;* Physiquement * ;**************** ;la prise LANC est un jack 2,5 mm 3 pôles (stéréo) femelle sur le caméscope. ;En partant de la pointe du jack on trouve le signal (collecteur ouvert), l'alimentation (5~6 volts) et la masse. ;******************** ;* Electroniquement * ;******************** ;le caméscope (en PAL) génère une trame de 8 mots de 9bits toutes les 20 millisecondes (ms) ;en absence de signal un pull-up ramène la tension du signal à l'alimentation, ;un bit dure 104 microseconde (µs), ;le bit est à un niveau logique 0 quand le collecteur (signal) est ouvert (U= 5~6volts), ;le bit est à un niveau logique 1 quand le collecteur est saturé (U= 0volt), ;un mot commence par un bit de start (1 = 0volts) suivit d'un octet LSB en premier ; avec le trv 33 on note 3 bits de stop à 0 (= 5volts)entre chaque mot. ;la trame d'information dure donc : ;(1 bit de start + 8 bits de data + 3bits de stop) x 104µs x 8 ;soit 9984µs. Il y a donc un espace à 0 entre trame de 20 ms - 9984µs = 10ms de signal à +5volts ! ;cette pause de 10 ms nous servira à détecter le début de trame. ;******************* ;* pour simplifier * ;******************* ;le premier et le deuxième octet servent de commande ;il faut envoyer H'18 H'30 pour la fonction stop ;il faut envoyer H'18 H'3A pour la fonction rec (enregistrement) ;le cinquième octet indique l'état du caméscope. On notera 3 valeurs: ;H'02 cam STOP, ;H'04 cam REC, ;H'14 cam REC/Pause ;les autres valeurs et octets permettent un tas d'autres choses comme le contrôle ;du Zoom, du doublage, du mode photo, ... ;et de connaître l'état de l'avancement de la bande, de l'heure, du memory stick,... ;bref, tout le nécessaire pour piloter toutes les fonctions du caméscope. ;************* ;* la notice * ;************* ;Pour indiquer la mise sous tension je fais clignoter la led pendant 20 ms toutes les 2 secondes. ;cela pour savoir s'il est possible d'enregistrer d'un coup d'oeil. ;Pour lancer l'enregistrement on appuie une fois sur le bouton poussoir. ;Pour indiquer que le cam enregistre la LED rouge reste allumée. ;Pour stopper l'enregistrement on appuie une nouvelle fois sur le bouton poussoir. ;on peut relancer l'enregistrement en ré appuyant sur le BP ainsi de suite. ;la seule subtilité est qu'en mode REC/pause (accessible uniquement par l'écran tactile du trv33) ;la LED clignote rapidement (4x par seconde) et le bouton poussoir est inopérant. ;****************** ;* l'organigramme * ;****************** ;On lit la trame complète que l'on stocke dans les registres lanc0 à lanc7. ;En fonction de l'octet n°4 (lanc4 on gère l'illumination de la LED rouge. ;on intègre l'état du bouton poussoir (BP). ;Si le BP n'est pas appuyé, on reboucle au début. ;Si le BP est appuyé, on génère une séquence de plusieurs trames de commande ;qui inversent l'état de l'enregistrement du caméscope. ;On reboucle au début. ;******************************************* ; Thanks to David Meed (dmeed@nbnet.nb.ca) ;******************************************* ;qui a mis a disposition le code de sa télécommande ;où j'ai emprunté les routines commentées en anglais. ;CHECKSUM : F78C ;***** registre du microcontroleur STATUS EQU H'0003' RP0 EQU H'0005' Z EQU H'0002' FSR EQU H'0004' INDF EQU H'0000' GPIO EQU H'0005' OPTION_REG EQU H'0081' TRISIO EQU H'0085' CMCON EQU H'0019' OSCCAL EQU H'0090' WPU EQU H'0095' ANSEL EQU H'009F' ;***** Configuration Bits _CPD_OFF EQU H'3FFF' _CP_OFF EQU H'3FFF' _BODEN_ON EQU H'3FFF' _MCLRE_OFF EQU H'3FDF' _PWRTE_ON EQU H'3FEF' _WDT_OFF EQU H'3FF7' _INTRC_OSC_NOCLKOUT EQU H'3FFC' PROCESSOR 12F675 ;oscillator rc interne, power up timer off, brown out detect on, reset interne __config _CPD_OFF&_CP_OFF&_BODEN_ON&_MCLRE_OFF&_PWRTE_ON&_WDT_OFF&_INTRC_OSC_NOCLKOUT ;configuration du port Sdata EQU .0 ;utiliser seulement pour la programmation Sclock EQU .1 ;utiliser seulement pour la programmation Svpp EQU .3 ;utiliser seulement pour la programmation BP EQU .2 ;bouton poussoir connecté entre ce port et la masse LED EQU .4 ;Led connectée entre ce port et le +5 volts à travers une résistance de 270 ohms LANC EQU .5 ;liaison direct au port LANC ;CONSTANTES DU PROGRAMME VGPIO EQU B'00010000' ;Pour que la LED soit éteinte il faut que le port soit à 1 (+5 volts) VTRISIO EQU B'11101111' ;seul le port de la LED est une sortie, LANC est une entrée ET une sortie VOPTION EQU B'00000101' ;Global Pull up enable VWPU EQU B'11111111' ;pull up sur tous les ports VCMCON EQU B'00000111' ;comparateur off VANSEL EQU B'00000000' ;digital I/O VCLI EQU .6 ;x20mS pour la péridoe de clignotement de la LED durant la REC/pause VIBP EQU .10 ;x20mS durée de l'intégration du bouton poussoir (BP) VBOUC EQU .3 ;nombre de répétition de l'ordre LANC VFLASH EQU .100 ;x20ms période du flash de mise sous tension ;REGISTRES DU PROGRAMME ;ram de 32 à 95 soit 64 octets SUTATS EQU .32 ;registre des FLAGs REC EQU .0 ;le cam enregistre EBP EQU .2 ;état du bouton poussoir après intégration (VIBP/CIBP) ABP EQU .3 ;indique que le BP vient d'être appuyé (après intégration) attente EQU .33 ;compteur pour les boucles d'attente attentea EQU .34 CLI EQU .35 ;compteur pour la période du clignotement de la LED (REC/pause) CBIT EQU .36 ;compteur pour le nombre de bit dans l'octet LANC CBYTE EQU .37 ;compteur du nombre d'octet dans la trame LANC lanc0 EQU .38 ;premier octet de la trame lanc lanc1 EQU .39 lanc2 EQU .40 lanc3 EQU .41 lanc4 EQU .42 lanc5 EQU .43 lanc6 EQU .44 lanc7 EQU .45 ;dernier octet de la trame LANC temp EQU .46 ;registre de travail temporaire CIBP EQU .47 ;compteur d'intégration du BP CBOUC EQU .48 ;compteur de boucle de répétition d'ordre LANC CFLASH EQU .50 ;compteur de la période du flash (mise sous tension) PREMIERE ORG .0 GOTO INIT ;vecteur après mise sous tension ,watch dog ou reset INTERRUPT ORG .4 retfie ;vecteur d'IT sans objet ;****************************** ;***** début du programme ***** ;****************************** INIT ORG .5 ;***** initialisation des SFRs MOVLW VGPIO ;état des sorties à la mise sous tension MOVWF GPIO MOVLW VCMCON ;comparateur off MOVWF CMCON BSF STATUS,RP0 ;accès aux registres de la page mémoire 1 CALL H'3FF' ;calibration du cycle à 1µs MOVWF OSCCAL ;avec la valeur calibrée en usine MOVLW VANSEL ;registre du CAN qui configure le type d'I/O MOVWF ANSEL MOVLW VTRISIO ;direction des ports MOVWF TRISIO MOVLW VOPTION ;pull-up, front d'IT, configuration du timer MOVWF OPTION_REG MOVLW VWPU ;pull-up sur tous le port MOVWF WPU BCF STATUS,RP0 ;retour aux registres de la page 0 ;***** initialisation des registres du programme clrf SUTATS ;initialisation du registre des flags movlw VCLI ;base de temps pour le clignotement movwf CLI movlw VIBP ;nombre d'intégration pour le BP movwf CIBP movlw VFLASH ;base de temps pour le clignotement "mise sous tension" movwf CFLASH ;***** détection du début de trame LANC sync_up clrf attente ;clear sync counter to 0 sync_loop btfss GPIO,LANC ;Wait for interframe gap goto sync_up ;This loop takes 6 us, so if the nop ;counter overflows before incfsz attente,f ;a transition on the LANC goto sync_loop ;line, it is the interframe gap.. ;(1530 us) ;************************************************************************ ;************************************************************************ ;*****initialisation de la boucle principale pour la lecture des 8 octets synced movlw .8 ;initialisation du compteur d'octet movwf CBYTE movlw lanc0 ;initialisation de l'adressage indirect movwf FSR ;de la table des 8 octets de la trame LANC ;***** debut de boucle pour la lecture de la trame LANC ;***** detection du bit de start wait_strt btfsc GPIO,LANC ; wait for start bit goto wait_strt ;***** pause de 50 µs pour se centrer au milieu du start bit movlw .14 call pause btfsc GPIO,LANC ;verification du bit de start goto sync_up ;erreur de synchronisation movlw .8 ;initialisation du compteur de bit movwf CBIT ;de l'octet en cours ;********************************************************************** ;***** debut de boucle pour la lecture d'un octet ;***** le timing doit respecter scrupuleusement les 104 µs de chaque bit byte1 movlw .30 ;pause de 96µs call pause read_bits rrf temp,f bcf temp,7 ; clear msb receive register btfss GPIO,LANC ; test lanc bit bsf temp,7 ; and set msb if set ; note that we are inverting the bit ; here - +5v becomes 0 and ; +0v becomes 1. decfsz CBIT,f ; continue to read bits until we have goto byte1 ; received 8 bits ;************************************************* ;***** fin du traitement de l'octet ;***** pause de 104 µs pour sortir du centre du dernier bit movlw .32 call pause ;***** sauvegarde de l'octet recombiné dans la table indexée movf temp,w movwf INDF incf FSR,f ;on passe à l'octet suivant decfsz CBYTE,f ;fin de trame ? goto wait_strt ;non ;***** à ce point la trame complète est mémorisée dans la table lanc0-7 ;********************************************************************** ;********************************************************************** ;***** visualisation de l'état du cam par la led bcf SUTATS,REC ;initialisation du flag de l'état de l'enregistrement teststop movlw 02h ;si l'octet 4 de la trame = 02h subwf lanc4,w ;le cam est stopé btfss STATUS,Z ;on fait donc flashé la LED pour une durée de 20ms goto testrec ;toutes les VFLASH x 20ms bsf GPIO,LED decfsz CFLASH,f ;Pour faire clignoter la LED goto BPdecode movlw VFLASH ;on décrémente CFLASH et movwf CFLASH ;quand il rejoint la valeur 0, on le recharge bcf GPIO,LED ;en allumant la LED pour un cycle de 20 ms goto BPdecode testrec movlw 04h subwf lanc4,w ;si l'octet 4 de la trame = 04h btfsc STATUS,Z ;le cam enregistre goto inrecordA ;on allume la LED testpause movlw 14h ;si octet 4 de la trame = 14h subwf lanc4,w ;le cam est en pause d'enregistrement btfss STATUS,Z ;on fait clignoter la LED goto stoprec ;sinon on l'éteint. pauserec decfsz CLI,f ;Pour faire clignoter la LED goto BPdecode ;on décrémente un compteur movlw VCLI ;pour définir une période multiple de 20ms movwf CLI ;[période d'une trame lanc] à l'issu de laquelle btfsc GPIO,LED ;on inverse l'état de la LED goto inrecord stoprec bsf GPIO,LED ;éteint la LED goto BPdecode inrecordA bsf SUTATS,REC inrecord bcf GPIO,LED ;allume la led ;***** intégration de l'appui sur la touche (anti rebond) ;il faut que le changement d'état du BP reste stable au moins pendant VIBP x 20ms ;pour que EBP suive sa logique. Au changement d'état on arme le flag ABP qui sera ;remis à 0 lorsque l'ordre sera envoyé afin d'éviter l'envoi en continu ;de l'ordre quand le BP est maintenu appuyé. BPdecode btfss GPIO,BP ;test BP goto bpap ;BP est appuyé bprel btfss SUTATS,EBP ;BP n'est pas appuyé goto initCIBP ;si précédement aussi on ne fait rien decfsz CIBP,f ;sinon on regarde s'il est relaché goto BPfin ;depuis suffisament longtemps bcf SUTATS,EBP ;pour changer son état à 0 goto initCIBP bpap btfsc SUTATS,EBP ;BP est appuyé goto initCIBP ;précédement aussi alors on ne fait rien decfsz CIBP,f ;sinon on regarde s'il est appuyé goto BPfin ;depuis suffisament longtemps bsf SUTATS,EBP ;pour changer son état à 1 bsf SUTATS,ABP ;et on indique que l'on vient de changer d'état initCIBP movlw VIBP ;initialisation du compteur d'intégration movwf CIBP ;dans l'attente d'un changement d'état ;***** il y a des ordres à envoyer ? BPfin btfss SUTATS,ABP goto sync_up ;non bcf SUTATS,ABP ;Oui, on désarme la lecture de la fonction movlw 18h ;code qui indique le type d'action à mener movwf lanc0 ;Normal command to VTR or Camera movlw 3Ah ;ordre rec btfsc SUTATS,REC ;inversons l'état de l'enregistrement movlw 30h ;ordre stop movwf lanc1 movlw .0 ;avec la valeur logique 0 movwf lanc2 ;on ne perurbe pas la fonction movwf lanc3 ;des 6 autres octets vu que movwf lanc4 ;le port LANC est en entrée haute impédance movwf lanc5 ;pour un 0 logique. En effet, le +5volts (0) est celui movwf lanc6 ;de l'alimentation ramené par le pull-up. movwf lanc7 movlw VBOUC ;initialisation du nombre de répétition de l'ordre movwf CBOUC ;deux ordres consécutifs suffisent. ;********************************************************************************** ;********************************************************************************** ;*****initialisation de la boucle principale pour l'écriture des 2 mots de commande ;***** suivis des 6 mots d'information reptram movlw .8 ;initialisation du compteur d'octet movwf CBYTE movlw lanc0 ;initialisation de l'adressage indirect movwf FSR ;***** debut de boucle pour l'écriture de la trame LANC ;***** detection du bit de start w_strt movlw .8 ;initialisation du compteur de bit movwf CBIT w_strt2 btfsc GPIO,LANC ; wait for start bit goto w_strt2 nop movf INDF,w movwf temp ;***** respect des 104 µs pour ce placer à la fin du bit de tart byte2 nop ;instant de la µs 8 nop movlw .28 ;=90 µs call pause btfss temp,0 goto W0 W1 bsf STATUS,RP0 ;port à 0 volt (1 logique) bcf TRISIO,LANC ;104µs à ce point bcf STATUS,RP0 bcf GPIO,LANC goto WS W0 bsf STATUS,RP0 ;port à 5 volts (0 logique) bsf TRISIO,LANC ;104µs à ce point bcf STATUS,RP0 nop nop WS rrf temp,f ;décompostion des bits de la commande par rotation circulaire decfsz CBIT,f ;fin de l'octet ? goto byte2 ;non bsf STATUS,RP0 ;rétablit le port en entrée bsf TRISIO,LANC bcf STATUS,RP0 ;************************************************* ;***** fin du traitement de l'octet ;***** pause de 50 µs pour sortir du dernier bit movlw .15 call pause incf FSR,f decfsz CBYTE,f ;fin de la commande ? goto w_strt ;non ;************************************************* ;************************************************* ;***** détection du début de trame LANC syncope clrf attente ;clear sync counter to 0 syncplooc btfss GPIO,LANC ;attente d'une pause inter trame goto syncope ;d'une durée minimale de incfsz attente,f ;256 x 5µs = 1280 µs goto syncplooc decfsz CBOUC,f ;fin de la répétition de la commande ? goto reptram ;non goto sync_up ;oui ;Si tu es arrivé à lire les commentaires jusqu'au bout sans être hyptnotisé, je te tire mon chapeau ! ;***** pause de 6µs + (w*3µs) pause movwf attente pauseA decfsz attente,f goto pauseA re return END ;****************** ;* LANC * ;* VERSION * ;* SIMPLE * ;* enregistrement * ;* LINO DE MARTIN * ;* Mai 2004 * ;******************