Bienvenue aux nouveaux arrivants sur FantasPic !

- Pensez à lire les règles durant votre visite, il n'y en a pas beaucoup, mais encore faut-il les respecter .
- N’hésitez pas à faire des remarques et/ou suggestions sur le Forum, dans le but de l'améliorer et de rendre vos prochaines visites plus agréables.
- Vous pouvez regarder votre "panneau de l'utilisateur" afin de configurer vos préférences.
- Un passage par "l'utilisation du forum" est recommandé pour connaître les fonctionnalités du forum.

--- L’équipe FantasPic ---
Forum général sur l'Assembleur !

Modérateur : mazertoc

suite 2 de Retour sur DCF77
JJE
Passioné
Passioné
Messages : 342
Âge : 78
Enregistré en : novembre 2017
Localisation : Picardie

#1 Message par JJE » dim. 16 déc. 2018 08:12

Bonsoir à tous,
Dans ce post, j' avais annoncé en préparer quelques autres sur les ourils utilisés dans ce programme.Voici le deuxième qui commente le module de multiplexage.
Quelques mots d'abord sur ce que j'appelle dans ces posts "module". Il s'agit pour moi d'une présentation d'un bloc de programme et de ses annexes (variables) cherchant à en faciliter la réutilisation dans le contexte le plus large possible. Formellement, c'est un fichier à inclure qui ne contient que des macros. Invoquer l'une d'elles dans son application revient à faire un copier/coller de son contenu dans le code de l'application avec l' avantage supplémentaire de pouvoir passer des paramètres. L'idéal, pour un tel module est qu'il soit totalement indépendant des contextes hard et soft. Hard, sur quel pic s'execute-it, comment les périphériques sont-ils mis en oeuvre. Soft : problèmes de banque mémoire et de pages de code. Il ne devrait être connu que par ses fonctionnalités et sa procédure de mise en oeuvre.

Je décris dans les lignes suivantes le cas de ce module de multiplexage qui prend en charge l'affichage sur 3 à 8 afficheurs 7 segments en n'utilisant que trois ports du processeur qui l'utilise.

Il utilise 3 ports en sortie du processeur qui va le faire tourner. Il serait très restricteur de les imposer à l'utilisateur.
Les 3 macros

Code : Tout sélectionner

; définition des broches utilisées
MPX_Strobe    macro port
, pin
    
#DEFINE    MPX_IO_Strobe    port, pin
    endm
MPX_Data    macro port
, pin
    
#DEFINE    MPX_IO_Data        port, pin
    endm
MPX_Clock    macro port
, pin
    
#DEFINE    MPX_IO_Clock    port, pin
    endm

permettent à l'utilisateur de préciser au module MPX quels sont les ports qu'il a prévu d'utiliser, Le module ne les connaissant que par l'intermédiaire de la constante définie par le #DEFINE.

Ce module, comme la plupart qu'on est amené à écrire, nécessite ses propres variables. Pour les insérer dans l'application, il suffit d'invoquer la macro
MPX_VAR comme on utilise une directive CBLOCK dans son code ; MPASM interdit d'invoquer une macro dans un CBLOCK, la macro développe donc un CBLOCK complet, sans adresse de départ qui est donc celle où on en est arrivé dans le précédent CBLOCK écrit, 0 par défaut. Remarquez que je ne connais pas de moyen avec MPASM de déclarer ces variables privées, par exemple, dans le cas présent, toutes le sont sauf, une MPX_Tampon. C'est une des raisons qui m'ont incité à préfixer leur étiquette de MPX_, a priori, l'utilisateur doit s'interdire d'utiliser ces étiquettes sauf celle qui est explicitement autorisée.

De la même manière, il n'est pas rare que des variables nécessitent une valeur initiale non nulle. C'est le rôle de la macro MPX_INIT_VAR qui d'une part permet de préciser le nombre d'afficheurs mis en oeuvre et d'autre part la fréquence de rafraîchissement. En passant, elle vérifie que l'application a bien défini l'une des constantes précisant le type d'afficheur utilisé (anode ou cathode commune). Le module MPX a bien sûr besoin de le savoir et ce n'est pas à lui d'en décider.
Bien que ce ne soit pas toujours le cas ce module nécessite un "démarrage". C'est le rôle de la macro MPX_InitMultiplex qui va lancer l'interruption timer0 sur laquelle repose le fonctionnement de ce module et qui sera appelée toutes les ms. A partir de ce moment, le tampon est affiché octet par octet, sans que l'utilisateur ait à s'en soucier. Pour modifier l'affichage, il suffit d'écrire dans l'octet du tampon visé la configuration de bits que l'utilisateur veut voir allumés.

C'est bien sûr à l'application de prendre en charge la gestion de l'interruption timer0, en particulier parcequ'elle peut avoir des traitements à faire en parallèle de MPX, avant ou après. Charge à elle d'appeler le module MPX en appelant le sous-programme MPX_IT_TIMER0 toutes les ms (1000micro-cycles)
C'est le rôle de la macro MPX_CODE d'installer dans l'application le code nécessaire à ce module, il doit résider dans une même page de code. Comme on n'y accède que par un call, PCLATH<4;3> sera initialisé sur la bonne page t, a priori, le module n'aura pas à s'en soucier.

Problème de banques mémoire : Si l'application utilise plusieurs banques, les variabless du modules doivent résider dans une même banque. J'ai trouvé préférable de laisser l'application gérer ce problème car elle seule connaît, au moment de l'exécution, la banque active et la banque où sont les variables de MPX, ce serait assez lourd, bien que plus sécuritaire de gérer ce problème au niveau du module, surtout si on veut rester indépendant du type de Pic. Dans l'exemple proposé, je n'utilise, bien que ce soit juste, qu'une seule banque mémoire

Le module utilise le registre FSR, il est donc nécessaire de le sauvegarder dans la routine d'interruption avant l'appel de MPX_IT_TIMER0. Dans l'exemple donné d'une utilisation de ce module, PCLATH est aussi sauvegardé, c'est parceque le troisième module utilisé en a besoin. Si seul MPX l'était, ce ne serait pas nécessaire

Voici le code de ce module

Code : Tout sélectionner

;******************************************************************
;
                                                                   
;    NOM:      Module Multiplex
;    Date création : 15/11/2018   
;    Circuit:  sans objet
;    Auteur:   JJE
;                                                                   
;******************************************************************
;
;
    Historique
;        Version 1.0 : 22/11/2018
;        Version 1.1 : 26/11/2018
;        Version 2.0 : 09/12/2018 
;            NON compatible avec V1.1
;            l'application prend en charge la sauvegarde et la
;            restauration des registres spéciaux nécessaires ce qui
;            facilitera l'
utilisation des IT de plusieurs modules
;                   Suppression de MPX_EQU ce qu'elle faisait et renvoyé
;                   dans MPX_INIT_VAR
;                   L'
application prend en charge la variable Timer0VAL
;
;******************************************************************
;
;
   Ressources utilisées
;       12 octets de données
;       34 octets de programme
;       l'interruption timer0
;       2 niveaux de pile + le niveau nécéssaire à l'
IT
;       3 ports en sortie du processeur utilisé
;
;******************************************************************
;
                             MACROS
;                       utiles à ce module
;******************************************************************

;
 initilise le numéro d'afficheur à utiliser comme afficheur 0
MPX_INITAFFICHEUR macro
    ifndef  ANODECOMMUNE
        ifndef  CATHODECOMMUNE
            error ""
            error "L'
une des constantes ANODECOMMUNE ou CATHODECOMMUNE doit être définie"
            error ""
        endif
    endif    
    ifdef  ANODECOMMUNE
        ifdef  CATHODECOMMUNE
            error ""
            error "
Une seule des constantes ANODECOMMUNE ou CATHODECOMMUNE doit être définie"
            error ""
        endif
    endif    
    ifdef    ANODECOMMUNE
        movlw    0xfe
    else
        movlw    0x01
    endif
    movwf    MPX_masqueAfficheur
    endm
    
; incrémente le numéro d'afficheur actif modulo NbAfficheurs
MPX_PROCHAINAFFICHEUR macro
    if    NbAfficheurs == 8
        ifdef    ANODECOMMUNE
            bsf        STATUS,C
            rlf        MPX_masqueAfficheur, f
            btfsc    STATUS, C
            goto    ici
        else
            bcf        STATUS,C
            rlf        MPX_masqueAfficheur, f
            btfss    STATUS, C
            goto    ici
        endif
    else
        ifdef    ANODECOMMUNE
            bsf        STATUS,C
            rlf        MPX_masqueAfficheur, f
            btfsc    MPX_masqueAfficheur, NbAfficheurs
            goto    ici
        else
            bcf        STATUS,C
            rlf        MPX_masqueAfficheur, f
            btfss    MPX_masqueAfficheur, NbAfficheurs
            goto    ici
        endif
    endif
    MPX_INITAFFICHEUR    
    local ici
ici        
    endm

;******************************************************************
;                             MACROS
;            utiles à l'Application utilisant ce module
;******************************************************************

; définition des broches utilisées
MPX_Strobe    macro port, pin
    #DEFINE    MPX_IO_Strobe    port, pin
    endm
MPX_Data    macro port, pin
    #DEFINE    MPX_IO_Data        port, pin
    endm
MPX_Clock    macro port, pin
    #DEFINE    MPX_IO_Clock    port, pin
    endm

; définition des variables de ce modules    
MPX_VAR    macro
    CBLOCK            ; Début de la zone des variables du module 
    MPX_DATA    : 0
    ; compteur utile à déclencher MPX_jobMultiplex    
    MPX_dojobMultiplex     : 1         
    ; variables servant au transfert des valeurs du tampon dans
    ; les afficheurs
    MPX_masqueAfficheur : 1    ; masque de l'afficheur exploité
    MPX_NuChiffre         : 1    ; rang dans MPX_Tampon du chiffre
                            ; à afficher
    MPX_Tampon : 8            ; les 8 octets en cours d'affichage
    ; variables du ssp de sortie MPX_SetRegWithW appelé
    ; par MPX_jobMultiplex
    MPX_CmptBits        : 1        ;compte les bits sortis
    MPX_HC4094Temp        : 1        ;rangement temporaire de la valeur
                                ; à écrire
    MPX_FINDATA            :0
    ENDC
    if (MPX_DATA && 0xf10) != (MPX_FINDATA && 0xf10)
        error "
La zone de variables de MPX doit résider dans une meme banque."                            
    endif
    endm    
    
; initialisation des variables de ce module
MPX_INIT_VAR macro   W, NBAFFICHEURS
    ifndef  ANODECOMMUNE
        ifndef  CATHODECOMMUNE
            error ""
            error "
L'une des constantes ANODECOMMUNE ou CATHODECOMMUNE doit être définie"
            error ""
        endif
    endif    
    ifdef  ANODECOMMUNE
        ifdef  CATHODECOMMUNE
            error ""
            error "Une seule des constantes ANODECOMMUNE ou CATHODECOMMUNE doit être définie"
            error ""
        endif
    endif    
dojobMultiplexVAL     EQU W    ; pour simuler unr IT toutes les
                            ; W*1000 microcycles
; définition du nombre d'
afficheurs en service
NbAfficheurs    EQU    NBAFFICHEURS
; vérification
    if     NbAfficheurs
<|| NbAfficheurs>8
     error 
"Le nombre d'afficheurs doit être compris ente 3 et 8"
    endif
    endm
    
MPX_InitMultiplex macro 
    
; on commence par l'affichage de l'octet 0 du tampon 
    
; sur l'afficheur 0
    MPX_INITAFFICHEUR
    clrf    MPX_NuChiffre
    movlw    dojobMultiplexVAL
    movwf    MPX_dojobMultiplex
    movwf    TMR0
    bsf        INTCON, PEIE        ; autoriser les IT périphériques
    bsf        INTCON, T0IE        ; autoriser l'
IT Timer0
    endm
    
MPX_CODE macro
    
;******************************************************************
;
                     IT Timer0
;******************************************************************

MPX_Début_Code
; doit être appelée par l'application toutes les 1ms
; (1000 micro-cycles)
MPX_IT_TIMER0
    decfsz    MPX_dojobMultiplex,f
    return

;******************************************************************
;                             MPX_jobMultiplex 
;******************************************************************
; MPX_dojobMultiplex s'
annule toutes les 4ms par le ssp d'IT Timer0
; active l'
afficheur défini par MPX_masqueAfficheur
; et lui fait afficher l'octet MPX_NuChiffre du tampon
; transfère les bonnes valeurs dans les HC4094
; MPX_masqueAfficheur et MPX_NuChiffre sont mis à jour 
; en vue  du prochain affichage
; consomme environ 460 microcycles
;MPX_jobMultiplex
    movlw    dojobMultiplexVAL
    movwf    MPX_dojobMultiplex
    bcf        MPX_IO_Strobe    
    movf    MPX_masqueAfficheur, w
    call     MPX_SetRegWithW
    MPX_PROCHAINAFFICHEUR
    movlw    MPX_Tampon
    addwf    MPX_NuChiffre,w
    movwf    FSR
    movf    INDF,w
    call     MPX_SetRegWithW
    bsf        MPX_IO_Strobe
    ; incrémente MPX_NuChiffre modulo NbAfficheurs    
    incf    MPX_NuChiffre,f
    movf    MPX_NuChiffre, w
    sublw    NbAfficheurs
    btfsc    STATUS, Z
    clrf    MPX_NuChiffre
    return
    
;******************************************************************
;                         ROUTINES DE SORTIE
;******************************************************************
; transfère le contenu de W dans le HC4094
; entrée :
;        W valeur à transférer
; sortie :
;        le registre est chargé mais le Strobe n'
a pas été fait
;        pour permettre d'utiliser ce sous-propgramme
;        pour charger plusieurs registres chaînés.
;        W n'
est pas modifié
; variables locales utilisées
;        MPX_HC4094Temp
;        MPX_CmptBits
; variables globales utilisées
;        néant
; durée 
;        186 cycles en comptant l'appel et le retour
MPX_SetRegWithW
    movwf    MPX_HC4094Temp        ; 2
    movlw    .8                ; nombre de bits à sortir
    movwf    MPX_CmptBits        ; 3
MPX_SetRegWithW_1
    rlf        MPX_HC4094Temp, F    ; 4 + 20*nb bits sortis
    btfss    STATUS, C        ; 5 + 20*nb bits sortis
    goto    MPX_SetRegWithW_2    ; 6 + 20*nb bits sortis
    bsf        MPX_IO_Data            ; 7 + 20*nb bits sortis
    goto    MPX_SetRegWithW_3    ; 8 + 20*nb bits sortis
MPX_SetRegWithW_2
    bcf        MPX_IO_Data            ; 8 + 20*nb bits sortis
    nop                        ; 9 + 20*nb bits sortis pour
                             ; équilibrer les deux cas
MPX_SetRegWithW_3
    bsf        MPX_IO_Clock        ; 10 + 20*nb bits sortis
    goto     $+1                ; 11 + 20*nb bits sortis
    goto     $+1                ; 13 + 20*nb bits sortis
    bcf        MPX_IO_Clock        ; 15 + 20*nb bits sortis
    goto     $+1                ; 16 + 20*nb bits sortis
    goto     $+1                ; 18 + 20*nb bits sortis
    decfsz    MPX_CmptBits, F        ; 20 + 20*nb bits sortis
    goto    MPX_SetRegWithW_1    ; 21 + 20*nb bits sortis
    return                    ; 182
MPX_Fin_Code    
    if (high(MPX_Fin_Code) && 0xf8) != (high(MPX_Début_Code) && 0xf8)
        error ""
        error "Le code du module MPX doit résider dans une même page"
        error ""
    endif
    endm


En rédigeant ce papier, j'ai apporté quelques modification sur la version utilisée dans le premier post qui rend le programme programme donné dans ce post incohérent avec la nouvelle version de MPX. Voici donc ce programme mis à niveau, ce sont des modifications de détail.

Code : Tout sélectionner

;******************************************************************
;
   PROGRAMME affiche la durée des pulses d'un module DCF77
;******************************************************************
;
;    NOM :      Affiche durées pulses
;    Date :     02/12/2018
;    Circuit :  Platine d'
essais
;    Auteur :   JJE
;
;******************************************************************
;
;
    Fichier requis: 
;                    p12F675.inc
;                    MacrosTest.inc
;                    Module Multiplex.inc
;                    Module DCF77.inc
;
;******************************************************************
;
;
   Historique :
;
       Version 1.0 :  12/12/2018
;       Version 1.1 :  14/12/2018
;           - suppression du relais relais_DCF77_DébutTrame qui ne
;             faisait rien et était resté là par erreur
;           - compléter quelques commentaires
;       Version 2
;            - Prise en charge de TIMER0VAL
;            - l'invocation de MPX_EQU et supprimée
;            - MPX_INIT_VAR prend en charge ce qu'
elle faisait
;            - prise en compte du changement de MPX_InitMultiplex
;              de sous-programme en macro
;            - ajouté le comptage des pertes de synchronisation
;******************************************************************
;
;
    Notes: Ce programme affiche successivement, toutes les 5ms,
;
 1 - en hexa la fourchette des durées des pulses lus
;     b0min, b0max, b1min, b1max (4 fois deux chiffres)
;
 2 - en hexa la fourchette des intervales entre deux fronts
;     montants
;     durée min durée max (deux fois quatre chiffres)
;
 3 - le jour et l'heure tels que donnés par le module DCF77
;     jour(1 à 7), tiret, heure, minutes, tiret, tiret
; 4 - le jour et la date tels que donnés par le module DCF77
;     jour(1 à 7), tiret, quantième, mois, année (2 chiffre de
;     droite)
;
; Tant que le module DCF77 ne s'
est pas synchronisé, les affichages
; 3 et 4 ne sont pas effectués (affichent  des tirets médians)
;
;******************************************************************


        #include "p12F675.inc"
        #include "../../MacrosTest.inc"
        #include "../../Module Multiplex/Programme/V2/Module Multiplex.inc"
        #include "../../Module DCF77/Programme/Module DCF77.inc"


;******************************************************************

    ; préciser ici les directives __CONFIG nécessaires
    __CONFIG   _CP_OFF 
& _WDT_OFF & _PWRTE_ON & _CPD_OFF & _BODEN_OFF & _MCLRE_OFF & _INTRC_OSC_NOCLKOUT


;******************************************************************
;
                        Les ports utilisés
;******************************************************************
;
 Renseigner le module Multiplexeur des ports utilisés
    MPX_Strobe    GPIO
, 0
    MPX_Data    GPIO
, 1
    MPX_Clock    GPIO
, 2
    
; Renseigner le module DCF77 du port utilisé
    DCF77_Port    GPIO
, 5
    
;******************************************************************

;
 conserver une et une seule des lignes suivantes, en fonction
; du hard
    
#define ANODECOMMUNE
;    #define CATHODECOMMUNE

; brochage sur la platine d'essai
    #DEFINE        segmenta    0x08    ; 0x1
    #DEFINE        segmentb    0x01    ; 0x2
    #DEFINE        segmentc    0x80    ; 0x4
    #DEFINE        segmentd    0x04    ; 0x80
    #DEFINE        segmente    0x02    ; 0x40
    #DEFINE        segmentf    0x40    ; 0x20
    #DEFINE        segmentg    0x20    ; 0x10
    #DEFINE        segmentDP    0x10    ; 0x8

;******************************************************************
; commandes des 7 segments
    ifdef    ANODECOMMUNE
Segmenta    EQU    segmenta^0xff
Segmentb    EQU    segmentb^0xff
Segmentc    EQU    segmentc^0xff
Segmentd    EQU    segmentd^0xff
Segmente    EQU    segmente^0xff
Segmentf    EQU    segmentf^0xff
Segmentg    EQU    segmentg^0xff
SegmentDP    EQU    segmentDP^0xff
; pour améliorer la mise en page du listing
Segmentsab    EQU    Segmenta & Segmentb
Segmentsac    EQU    Segmenta & Segmentc
Segmentsbc    EQU    Segmentb & Segmentc
Segmentsef    EQU    Segmente & Segmentf
Segmentsabc    EQU    Segmenta & Segmentb & Segmentc
Segmentsefg    EQU    Segmente & Segmentf & Segmentg
    else
Segmenta    EQU    segmenta
Segmentb    EQU    segmentb
Segmentc    EQU    segmentc
Segmentd    EQU    segmentd
Segmente    EQU    segmente
Segmentf    EQU    segmentf
Segmentg    EQU    segmentg
SegmentDP    EQU    segmentDP
; pour améliorer la mise en page du listing
Segmentsab    EQU    Segmenta + Segmentb
Segmentsac    EQU    Segmenta + Segmentc
Segmentsbc    EQU    Segmentb + Segmentc
Segmentsef    EQU    Segmente + Segmentf
Segmentsabc    EQU    Segmenta + Segmentb + Segmentc
Segmentsefg    EQU    Segmente + Segmentf + Segmentg
    endif
    ifdef    ANODECOMMUNE
chiffre0    EQU    Segmentsab & Segmentc & Segmentd & Segmentsef
chiffre1    EQU    Segmentb & Segmentc
chiffre2    EQU    Segmentsab & Segmentd & Segmente & Segmentg
chiffre3    EQU    Segmentsab & Segmentc & Segmentd & Segmentg
chiffre4    EQU    Segmentb & Segmentc & Segmentf & Segmentg
chiffre5    EQU    Segmentsac & Segmentd & Segmentf & Segmentg
chiffre6    EQU    Segmenta & Segmentc & Segmentd & Segmentsefg
chiffre7    EQU    Segmenta & Segmentb & Segmentc
chiffre8    EQU    Segmentsabc & Segmentd & Segmentsefg
chiffre9    EQU    Segmentsab & Segmentc & Segmentf & Segmentg
chiffreA    EQU    Segmentsab & Segmentc & Segmentsefg
chiffreB    EQU    Segmentc & Segmentd & Segmentsefg
chiffreC    EQU    Segmenta & Segmentd & Segmente & Segmentf
chiffreD    EQU    Segmentsbc & Segmentd & Segmente & Segmentg
chiffreE    EQU    Segmenta & Segmentd & Segmentsef & Segmentg
chiffreF    EQU    Segmenta & Segmentsefg
chiffreVide    EQU 0xff
point        EQU SegmentDP
tiretB        EQU    Segmentd 
tiretM        EQU    Segmentg 
tiretH        EQU    Segmenta
    else
chiffre0    EQU    Segmentsab + Segmentc + Segmentd + Segmentsef
chiffre1    EQU    Segmentb + Segmentc
chiffre2    EQU    Segmentsab + Segmentd + Segmente + Segmentg
chiffre3    EQU    Segmentsab + Segmentc + Segmentd + Segmentg
chiffre4    EQU    Segmentb + Segmentc + Segmentf + Segmentg
chiffre5    EQU    Segmentsac + Segmentd + Segmentf + Segmentg
chiffre6    EQU    Segmenta + Segmentc + Segmentd + Segmentsefg
chiffre7    EQU    Segmenta + Segmentb + Segmentc
chiffre8    EQU    Segmentsabc + Segmentd + Segmentsefg
chiffre9    EQU    Segmentsab + Segmentc + Segmentf + Segmentg
chiffreA    EQU    Segmentsab + Segmentc + Segmentsefg
chiffreB    EQU    Segmentc + Segmentd + Segmente + Segmentsefg
chiffreC    EQU    Segmenta + Segmentd + Segmente + Segmentf
chiffreD    EQU    Segmentsbc + Segmentd + Segmente + Segmentg
chiffreE    EQU    Segmenta + Segmentd + SegmentSef + Segmentg
chiffreF    EQU    Segmenta + Segmente + Segmentf + Segmentg
chiffreVide    EQU 0x00
point        EQU SegmentDP
tiretB        EQU    Segmentd 
tiretM        EQU    Segmentg 
tiretH        EQU    Segmenta
    endif
;    
;******************************************************************
;; quelques constantes pour MPX
;    ; préciser la durée en ms d'
affichage des afficheurs.
;
    ; pour une fréquence de 4MH, prescaler de 4
;    ; .9 est bon pour le premier paramètre, qui produit une IT
;    ; toutes les ms
;    ; pour 8 afficheurs,.4 est bon pour le deuxième
;    ; .8 est le nombre d'afficheurs utilisés
;    MPX_EQU    .9, .4, .8
TIMER0VAL       EQU .9
Nb_ITVAL        EQU .20        ; pour simuler unr IT toutes les 
                            ; 20.000 microcycles (20ms)
Cmpt_SecondeVAL EQU    .50    ; pour simuler une IT toutes les secondes
job0VAL         EQU .5    ; pour simuler une IT toutes les 5"
                        ; changement du type d'
affichage

    errorlevel 
-302
    

;******************************************************************
;
 valeurs initiales des registres spéciaux

OPTIONVAL    EQU    B
'10000001'        ; bit 7 = 1 : GPIO pull-ups disabled
                                
; bit 6 = 0 : sans objet
                                
; bit 5 = 0 : internal cycle clock
                                
; bit 4 = 0 : sans objet
                                
; bit 3 = 0 : prescaler is assigned
                                
; to  TIMER0 module
                                
; bit 2-= 001 : prescaler rate 1:4
                                
; cf page 14 du DataSheet
TRISIOVAL   EQU B
'00110000'        ; GPIO4 et 5 en entrée

IOCVAL        EQU B
'00100000'        ; IOC sur GP5
ANSELVAL    EQU B
'00000000'        ; ADCS<2:0> = 000 sans objet
                                
; ANS3: ANS0 = 0000 pas d'analogique
                                ; cf page 46 du DataSheet
INTCONVAL    EQU    B'
11000000'        ; bit 7 = 1 : Enables unmasked
                                ; interrupts
                                ; bit 6 = 1 : Enables all
                                ; peripheral interrupts
                                ; bit 5 = 0 : disables TMR0
                                ; interrupt 
                                ; bit 4 = 0 : disables GPIO port
                                ; change interrupt
                                ; bit 3-0 = 0 sans objet
                                ; cf page 15 du DataSheet

;******************************************************************
;                             MACROS
;******************************************************************

BANK1 macro
    bsf        STATUS,RP0
    endm

BANK0 macro
    bcf        STATUS,RP0
    endm

ADD_POINT macro
    ifdef ANODECOMMUNE
        andlw    point
    else
        iorlw    point    
    endif
    endm

; convertit le contenu de V,
; en ce qu'
il faut mettre dans add et add+1, supposés 2 octets du 
; tampon, pour afficher sa valeur en hexa
SORT8 macro    V
, add
    movf    V
, w
    andlw    0x0f
    call    convertir
    movwf    add 
+ 1
    swapf    V
, w
    andlw    0x0f
    call    convertir
    movwf    add
    endm
; idem V variable 16 bits Bas poids en tête    
SORT16 macro    V
, add
    SORT8    V
, add+2
    SORT8    V
+1, add
    endm
    
; met A à 0, A variable 16 bits
CLRF16F    macro    A
    clrf    A
    clrf    A
+1
    endm
    
; copie A dans AA, variables 16 bits
MOV16F macro    A
, AA
    movf    A
, w
    movwf    AA
    movf    A
+1, w
    movwf    AA
+1
    endm

; incrémente A, variable 16 bits bas poids en tête
; retourne Z armé si dépassement de capacipé (résultat nul),
;
 clear sinon
INCF16    macro    A
    incf    A
, f
    btfsc    STATUS
, Z
    incf    A
+1, f
    endm

; call SSP avec gestion éventuelle de PCLATH
; sans intérêt pour un 12F675 qui n'a qu'une page programme
; utile pour les pics à plusieurs pages de programme
MYCALL macro    SSP
; Dans ce programme, ON SAIT QUE L'APPELANT EST EN PAGE 0        
    if ((HIGH SSP) & 0x18)!= .0    ; on est en page 0
        ; si SSP n'
y est pas, il faut renseigner PCLATH
        movlw    HIGH SSP        
        movwf   PCLATH
        call    SSP
        clrf    PCLATH
    else
        call    SSP
    endif
    endm

;******************************************************************
;
                   DECLARATIONS DE VARIABLES
;******************************************************************

    CBLOCK 0x020                   ; Début de la zone des variables  
    
; sauvegardes pour l'IT
    w_temp : 1                    ; W
    status_temp : 1                ; STATUS
    FSR_temp    : 1
    PCLATH_temp    : 1
    endc
    
    ; réserve l'
espace nécessaire au module Multiplex
    MPX_VAR
    
; réserve l'espace nécessaire au module DCF77
    DCF77_VAR
    
    CBLOCK
    ; les variables de ce programme
    Nb_IT            : 1            ; compteur d'
IT pour Nb_ITVAL ms
    Cmpt_Seconde    
: 1            ; compteur pour IT 1"
    
    ; variables pour déclencher les actions requises
    ; dans la boucle principale
    dojob    : 1                ; ensemble de flags pour job0 à job2
    Cmpt_job0    : 1         ; décompteur pour déclencher job0
    TypeAffichage    : 1     ; type d'affichage à mettre en oeuvre
                            ; au prochain appel de job0 (<1;4>
    Cmpt_Inter_FM        : 0    ; compteur 16 bits utile pour compter
                            ; la durée inter fronts montants
    Cmpt_Inter_FM_BP     : 1    
    Cmpt_Inter_FM_HP    : 1
    Cmpt_Inter_FM_Min    : 2    ; mini de Cmpt_Inter_FM
    Cmpt_Inter_FM_Max    : 2    ; maxi de Cmpt_Inter_FM
    Cmpt_Inter_FM_tmp     : 0    ; la durée inter fronts montants
                            ; en cours
    Cmpt_Inter_FM_BP_tmp     : 1    ; bas poids
    Cmpt_Inter_FM_HP_tmp    : 1    ; haut poids
    Cmpt_DuréePulse        : 1    ; Compteur durée d'un pulse
    Cmpt_DuréePulse_tmp    : 1    ; Compteur durée d'un pulse en cours
    Cmpt_DuréePulse0Min    : 1    ; mini de Cmpt_DuréePulse bit 0
    Cmpt_DuréePulse0Max    : 1    ; maxi de Cmpt_DuréePulse bit 0
    Cmpt_DuréePulse1Min    : 1    ; mini de Cmpt_DuréePulse bit 1
    Cmpt_DuréePulse1Max    : 1    ; maxi de Cmpt_DuréePulse bit 1
    
;******************************************************************
;                     variables locales aux sous-programmes
;******************************************************************
    ; variables du ssp de sortie SetRegWithW appelé par Job1
    CmptBits        : 1        ; compe les bits sortis
    HC4094Temp        : 1        ; rangement temporaire de la valeur
                            ; à écrire
    ; variables utilisées uniquement par convertDCB
    convert_tempHP    : 1
    convert_tempBP    : 1
    ; compteur du ssp wait
    wait_temp        : 1            
    ; variables utilisées uniquement par le remplissage du tampon
    RemplirTampon_temp    : 1
    cmpt_remplirTampon     : 1
    cmpt_Perte_Synchro  : 1
    lastData            : 1
    ENDC                        ; Fin de la zone 
                           
    if    lastData>=0x60 
        error "
les variables doivent être en banque 0"
    endif

    ; si l'application utilise la banque mémoire 1
    ; les lignes suivantes sont nécessaires
    ; ici, ce n'est pas le cas
;    CBLOCK    0xA0
;    sauvegardeIT    : 2    
;    ENDC

;******************************************************************
;                 constantes facilitant l'accès au tampon
;                        et la lecture du code
;******************************************************************
; des valeurs en cours d'affichage
TamponOsccalHP            EQU    MPX_Tampon+2
TamponOsccalBP            EQU    MPX_Tampon+3
TamponDuréePulse0Min    EQU    MPX_Tampon
TamponDuréePulse0Max    EQU    MPX_Tampon+2
TamponDuréePulse1Min    EQU    MPX_Tampon+4
TamponDuréePulse1Max    EQU    MPX_Tampon+6
TamponInterFMMin        EQU    MPX_Tampon
TamponInterFMMax        EQU    MPX_Tampon+4
TamponJour                EQU    MPX_Tampon
TamponHeure                EQU    MPX_Tampon+2
TamponMinute            EQU    MPX_Tampon+4
TamponQuantième            EQU    MPX_Tampon+2
TamponMois                EQU    MPX_Tampon+4
TamponAnnée                EQU    MPX_Tampon+6
TamponPerte_Synchro     EQU    MPX_Tampon+6

; les flags pour marquer les tâches à faire
dojob0                    EQU 0    ; flag utile à déclencher job0
dojob1                    EQU    1    ; flag utile à déclencher job1
dojob2                    EQU    2    ; flag utile à déclencher job2
dojob3                    EQU 3    ; clear tant que pas vu de front
                                ; montant
dojob4                    EQU 4    ; set pour traiter Cmpt_DuréePulse
                                ; après avoir reçu le premier
                                ; front montant sur PortDCF77
dojob5                    EQU 5    ; set pour afficher heure et date
                                ; dès que DCF77 le dit
                                ; reset dès que perte de synchro
dojob6                    EQU 6    ; set dès que DCF77 dit être 
                                ; synchronisé
    errorlevel -302
    
;******************************************************************
;                      DEMARRAGE SUR RESET
;******************************************************************

    org     0x000                 ; Adresse de départ après reset
       goto    init
;******************************************************************
;                     ROUTINE INTERRUPTION
;******************************************************************
            ;sauvegarder registres    
            ;---------------------
    ORG     0x004                ; adresse d'interruption
    
    ; interruption reçue toutes les 1ms
    movwf    w_temp              ; 1 sauver registre W
    swapf    STATUS,w            ; 2 swap status avec résultat dans w
    movwf    status_temp            ; 3 sauver status swappé
    
    BANK0
    
    movf    FSR, w                ; 4
    movwf    FSR_temp            ; 5
    movf    PCLATH, w            ; 6
    movwf    PCLATH_temp            ; 7
    clrf    PCLATH                ; 8

    BANK0
    btfsc    INTCON,T0IE            ; 4/5 tester si interrupt timer autorisée
    btfss    INTCON,T0IF            ; 5/6 oui, tester si interrupt timer en cours
    goto     IT_1                ; 7 non, c'est une autre interrupt
    bcf        INTCON,T0IF            ; 7 effacer flag interrupt timer
    movlw    TIMER0VAL            ; 9        
    movwf    TMR0                ; 10
    ; à ce moment, TIMER0 va compter 988 [(256-9)*4] micro-cycles
    ; et reviendra au début de ce sous-programme de gestion des IT
    ; ce qui compte tenu des instructions qui précèdent et des deux
    ; non décomptées après l'initialisation de TMR0 ammène bien à
    ; 1000 micro-cycles, soit 1000 microsecondes
    
    ; fait le travail du module MPX
    MYCALL    MPX_IT_TIMER0
    ; fait le travail du module DCF77
    MYCALL    DCF77_IT_TIMER0
    ; fait le travail local de ce programme
    call    IT_Timer0
    goto    restaurereg
IT_1    
    btfsc    INTCON,GPIE        ; tester si IT GPIO autorisée
    btfss    INTCON,GPIE        ; oui, tester si IT GPIO en cours
    goto     IT_2
    movf    GPIO, w
    bcf        INTCON,GPIF
    ; fait le travail du module DCF77
    MYCALL    DCF77_IT_GPIO
    ; fait le travail local de ce programme
    call    intgpio                ; aller la traiter
; pas d'autre IT à gérer dans ce programme
; si IT_3 est utile, il faut garder les deux instructions suivantes
    ; clrf    PCLATH
    ; goto restaurereg
IT_2
; restaurer lesregistres
restaurereg
    movf    FSR_temp, w            ; 4 restaurer FSR avant STATUS
    movwf    FSR                    ; 5
    movf    PCLATH_temp, w        ; 6
    movwf    PCLATH                ; 7
    swapf    status_temp,w        ; 2 swap ancien status
    movwf   STATUS                ; 3 restaurer status
    swapf   w_temp,f            ; 6 Inversion L et H de l'ancien W
                                   ; sans modifier Z
    swapf   w_temp,w              ; 7 Réinversion de L et H dans W
                                ; W restauré sans modifier status
    retfie                      ; 8 return from interrupt

;******************************************************************
;                         TABLES DE CONVERSION
;       placées ici pour ne pas avoir de soucis avec PCLATH
;******************************************************************
; convertir la valeur présente dans W <0:15> en la valeur à envoyer
; au HC4094 pour un affichage de ce chiffre sur le TDS0316
convertir
    addwf    PCL,f
    retlw     chiffre0
    retlw     chiffre1
    retlw     chiffre2
    retlw     chiffre3
    retlw     chiffre4
    retlw     chiffre5
    retlw     chiffre6
    retlw     chiffre7
    retlw     chiffre8
    retlw     chiffre9
    retlw     chiffreA
    retlw     chiffreB
    retlw     chiffreC
    retlw     chiffreD
    retlw     chiffreE
    retlw     chiffreF
    
fintables
    if high(fintables-1) != high(convertir)
        error    "
Les tables franchissent une frontière de bloc."
    endif

;******************************************************************
;                     INTERRUPTION TIMER 0
;******************************************************************
; Cette routine est appelée toutes les 1ms
IT_Timer0
    INCF16    Cmpt_Inter_FM_tmp
    btfsc    dojob, dojob4
    incf    Cmpt_DuréePulse_tmp, f
    decfsz    Nb_IT, f
    return
    ; ici, on passe toutes les Nb_ITVAL ms (20ms)
    ; on réinitialise le compteur de passages
    movlw     Nb_ITVAL
    movwf    Nb_IT
    decfsz    Cmpt_Seconde, f
    return
    ; ici, on passe toutes les Nb_ITVAL*Cmpt_SecondeVAL ms
    ; (20*50=1000ms), on réinitialise le compteur de passages
    movlw    Cmpt_SecondeVAL
    movwf    Cmpt_Seconde
    ; décrémenter wait_temp si besoin, pour sortir du SSP wait
    movf    wait_temp, f
    btfss    STATUS, Z
    decf    wait_temp, f
    ; décrémenter Cmpt_job0 si besoin,
    ; pour lancer job0 toutes les 5ms
    movf    Cmpt_job0, f
    btfss    STATUS, Z
    decfsz    Cmpt_job0, f
    return
    ; ici, on passe toutes les job0VAL s (5"
)
    ; on réinitialise le compteur de passages
    movlw    job0VAL
    movwf    Cmpt_job0
    bsf        dojob
, dojob0
    return
    
;******************************************************************
;
                     INTERRUPTION GPIO
;******************************************************************
intgpio
    btfsc    PortDCF77
    goto    intgpio_1                
    
; front descendant
    
; arrêter de mesurer la durée du pulse
    bcf        dojob
, dojob4
    
; sauve la valeur mesurée
    movf    Cmpt_DuréePulse_tmp
, w
    movwf    Cmpt_DuréePulse
    
; et réinitialise la variable
    clrf    Cmpt_DuréePulse_tmp
    bsf        dojob
, dojob1
    return                    
intgpio_1
    
; front montant
    bsf        dojob
, dojob4
    btfss    dojob
, dojob3
    goto    intgpio_1_1        
; si c'est le premier front montant
    ; sauve la valeur mesurée
    MOV16F    Cmpt_Inter_FM_tmp, Cmpt_Inter_FM
    ; et réinitialise la variable
    CLRF16F    Cmpt_Inter_FM_tmp
    bcf        dojob, dojob3
    bsf        dojob, dojob2
    return
intgpio_1_1
    bsf        dojob, dojob3
    ; et réinitialise la variable
    CLRF16F    Cmpt_Inter_FM_tmp
    return

;******************************************************************
;                       PROGRAMME PRINCIPAL
;******************************************************************
                    ; Initialisations
                    ; ---------------
init
    clrf    GPIO                ; Sorties à 0
    
    BANK1                ; sélectionner banque 1
                    
                    ; calibrer l'
oscilateur interne 
                    
; -----------------------------
;
 sur mon PIC, le call 0x3ff plante !
;
    movlw    0x40    
;    movlw    0x44    
;    movlw    0x2C    
;    movlw    0x5C    
;    movlw    0x6C    
;    movlw    0x64    
;    movlw    0x60
    movlw    0x4c
    movwf   OSCCAL


                    
; initialiser les registres spéciaux
                    
; -----------------------------------
    movlw    OPTIONVAL            ; charger masque
    
    movwf    OPTION_REG            
; initialiser registre option
    movlw    TRISIOVAL
    movwf     TRISIO
    movlw   ANSELVAL
    movwf   ANSEL
    movlw    IOCVAL
    movwf    IOC                    
; initialise IOC
    BANK0
    movlw     INTCONVAL
    movwf    INTCON                
; initialise INTCON

                    
; Effacer RAM banque 0
                    
; --------------------
    ; on se contente d'effacer les @ de 0x20 à 0x5f
    ; puisque l'
on n'utilise pas la banque 1
    movlw    0x020                ; initialisation pointeur
    movwf    FSR                    ; pointeur d'
adressage indirect
init1
    clrf    INDF                
; effacer ram
    incf    FSR
,f                ; pointer sur suivant
    btfss    FSR
,6                ; tester si fin zone atteinte (>=40)
    goto    init1                ; non, boucler
    btfss    FSR
,5                ; tester si fin zone atteinte (>=60)
    goto    init1                ; non, boucler

                    
; initialisations spécifiques
                    
; ---------------------------
    ; la doc du module Multiplex indique que certaines variables
    
; doivent être initialisées, laissons le faire
    
; préciser la durée en ms d'affichage des afficheurs.
    ; pour une fréquence de 4MH, prescaler de 4
    ; pour 8 afficheurs,.4 est bon pour le premier
    ; .8 est le nombre d'
afficheurs utilisés
    MPX_INIT_VAR .4
, .8
    
; idem pour le module DCF77
    DCF77_INIT_VAR
    
    
; des variables exigeant un valeur initiale non nulle
    movlw    Nb_ITVAL
    movwf    Nb_IT
    
; pour mesurer les secondes
    movlw    Cmpt_SecondeVAL
    movwf    Cmpt_Seconde
    
; initialise le compteur  de durée d'affichage
    movlw    job0VAL
    movwf    Cmpt_job0
    ; des minima improbables
    movlw   0xff
    movwf    Cmpt_Inter_FM_Min
    movwf    Cmpt_Inter_FM_Min+1
    movwf    Cmpt_DuréePulse0Min
    movwf    Cmpt_DuréePulse1Min
    ; nettoyer le tampon
    call    RemplirTamponAvec_chiffreVide    
    ; c'
est MPX_InitMultiplex qui lance l'IT timer0
    MPX_InitMultiplex
    call    Tests_Affichage        ; affiche des 8.
    movlw    .2
    call    wait
    ; affichage OSCCAL pour info
    call    RemplirTamponAvec_tiretM    
    BANK1
    movf    OSCCAL, w
    BANK0
    movwf    RemplirTampon_temp
    SORT8    RemplirTampon_temp, TamponOsccalHP
    movlw    .5
    call    wait
    
; on autorise l'
IT GPIO
    bsf        INTCON
, GPIE
    
; pour commencer par l'affichage 0    
    movlw   0xff
    movwf   TypeAffichage
    movlw    job0VAL
    movwf    Cmpt_job0

;******************************************************************
;                       Boucle principale
;                       -----------------
;******************************************************************
bcl0
    btfsc    dojob, dojob0
    call    job0
    btfsc    dojob, dojob1
    call    job1
    btfsc    dojob, dojob2
    call    job2
    goto     bcl0
    
;******************************************************************
;                             Appels du module DCF77
;******************************************************************
relais_DCF77_jobDate
    bsf dojob, dojob5
    bsf dojob, dojob6
    return
relais_DCF77_jobPerteSynchro
    bcf dojob, dojob5
    incf    cmpt_Perte_Synchro, f
    return
;******************************************************************
;                                     JOB0
;******************************************************************
; transfère dans le tampon, les valeurs à afficher
; en fonction de la valeur de TypeAffichage <0 ; 3> 
; TypeAffichage est incrémenté modulo 4 avant l'
appel pour
; faciliter la codage du goto calculé
job0
    bcf        dojob
, dojob0
    
; nettoyer le tampon
    call    RemplirTamponAvec_tiretM
    
; incrémenter le type d'affichage modulo 4 
    incf    TypeAffichage, f
    movlw    0x03
    andwf    TypeAffichage, w
    ; et appeler le ssp associé    
    movwf    TypeAffichage
    addwf    PCL, f
    goto    affiche0
    goto    affiche1
    goto     affiche2
    goto    affiche3
affiche0
    ; affiche DuréePulseMin et Max
    SORT8    Cmpt_DuréePulse0Min, TamponDuréePulse0Min
    SORT8    Cmpt_DuréePulse0Max, TamponDuréePulse0Max
    SORT8    Cmpt_DuréePulse1Min, TamponDuréePulse1Min
    SORT8    Cmpt_DuréePulse1Max, TamponDuréePulse1Max
    return
affiche1
    ; affiche Cmpt_Inter_FM_Min et Max
    SORT16    Cmpt_Inter_FM_Min, TamponInterFMMin
    SORT16    Cmpt_Inter_FM_Max, TamponInterFMMax
    return
affiche2
    btfss   dojob, dojob5
    goto    affiche2_1
    ; affiche le jour et l'
heure 
    
; jour, tiret, heure, minutes
    movf    DCF77_Précédent_jour
, w
    call    convertir
    movwf    TamponJour
    movlw    TamponHeure
    movwf    FSR
    movf    DCF77_Précédent_heure
, w
    call    convertDCB
    
; ici, FSR = TamponMinute
    movf    DCF77_Précédent_minute
, w
    call    convertDCB
    return
affiche2_1
    
; DCF77 n'est pas synchronisé
    call    RemplirTamponAvec_tiretH
    goto    affiche3_2
affiche3
    btfss   dojob, dojob5
    goto    affiche3_1
    ; affiche la date
    ; jour, tiret, quantième, mois, année(2 chiffres bas poids)
    movf    DCF77_Précédent_jour, w
    call    convertir
    movwf    TamponJour
    movlw    TamponQuantième
    movwf    FSR
    movf    DCF77_Précédent_quantième, w
    call    convertDCB
    ; ici, FSR = TamponMois
    movf    DCF77_Précédent_mois, w
    call    convertDCB
    ; ici, FSR = TamponAnnée
    movf    DCF77_Précédent_année, w
    call    convertDCB
    return
affiche3_1
    ; DCF77 n'
est pas synchronisé
    call    RemplirTamponAvec_tiretB
affiche3_2
    btfss   dojob
, dojob6
    
; s'il ne l'a pas encore été, ne rien faire d'autre
    return
    ; s'
il l'a déjà été, afficher le nombre de perte de synchro
    SORT8    cmpt_Perte_Synchro, TamponPerte_Synchro
    return
    
;******************************************************************
;                                     JOB1
;******************************************************************
; une nouvelle DuréePulse vient d'
être mesurée,
;
 mettre à jour Cmpt_DuréePulse0Min et Cmpt_DuréePulse0Max
; et Cmpt_DuréePulse1Min et Cmpt_DuréePulse1Max
; en conséquence. L'affichage sera mis à jour en son temps
job1
    bcf        dojob, dojob1
    Si     Cmpt_DuréePulse, StrictInfLit, .150, jump, job1_bit0
    Si    Cmpt_DuréePulse, StrictInf, Cmpt_DuréePulse1Min, jump, job1_bit1_1
    Si    Cmpt_DuréePulse, StrictSup, Cmpt_DuréePulse1Max, jump, job1_bit1_2
    return
job1_bit1_1
    ; filtre les valeurs supérieures à 240
    Si Cmpt_DuréePulse, StrictSupLit, .240, jump, job1_bit0_3
    movf    Cmpt_DuréePulse, w
    movwf    Cmpt_DuréePulse1Min
    return
job1_bit1_2
    movf    Cmpt_DuréePulse, w
    movwf    Cmpt_DuréePulse1Max
    return
job1_bit0    
    ; filtre les valeurs inférieures à 32 (valeur choisie un peu
    ; au hazard sert de filtre soft des parasites
    Si Cmpt_DuréePulse, StrictInfLit, .32, jump, job1_bit0_3
    Si Cmpt_DuréePulse, StrictInf, Cmpt_DuréePulse0Min, jump, job1_bit0_1
    Si Cmpt_DuréePulse, StrictSup, Cmpt_DuréePulse0Max, jump, job1_bit0_2
    return
job1_bit0_1
    movf    Cmpt_DuréePulse, w
    movwf    Cmpt_DuréePulse0Min
    return
job1_bit0_2
    movf    Cmpt_DuréePulse, w
    movwf    Cmpt_DuréePulse0Max
job1_bit0_3
    return
    
;******************************************************************
;                                     JOB2
;******************************************************************
; une nouvelle Cmpt_Inter_FM vient d'
être mesurée,
;
 mettre à jour Cmpt_Inter_FM_Min et Cmpt_Inter_FM_Max
; en conséquence. L'affichage sera mis à jour en son temps
job2
    bcf        dojob, dojob2
    ; filtrer les valeurs inférieures à 0x100 (Cmpt_Inter_FM_HP==0)
    movf    Cmpt_Inter_FM_HP, f
    btfsc   STATUS, Z
    goto    job2_3
    ; et les valeurs supérieures à 0x600 (bit 59 d'
une trame)
    Si      Cmpt_Inter_FM_HP, SupOuEgalLit, .6, jump, job2_3
    Si16    Cmpt_Inter_FM
, StrictInf, Cmpt_Inter_FM_Min, jump, job2_1
    Si16    Cmpt_Inter_FM
, StrictSup, Cmpt_Inter_FM_Max, jump, job2_2
    return
job2_1
    MOV16F    Cmpt_Inter_FM
, Cmpt_Inter_FM_Min
    return
job2_2
    MOV16F    Cmpt_Inter_FM
, Cmpt_Inter_FM_Max
job2_3
    return

;******************************************************************
;
                                     convertDCB
;******************************************************************
;
 convertit le contenu de W, nombre écrit en DCB
; en ce qu'il faut mettre dans les TDSO316 
; pour afficher sa valeur dans les octets pointés
; par FSR haut poids puis bas poids
; en sortie FSR pointe l'
octet suivant
convertDCB
    movwf    convert_tempHP
    movlw    0x0f
    andwf    convert_tempHP
,w
    movwf    convert_tempBP
    swapf    convert_tempHP
,w
    andlw    0x0f
    movwf    convert_tempHP
    movf    convert_tempHP
, w
    call    convertir
    movwf    INDF
    incf    FSR
, f
    movf    convert_tempBP
, w
    call    convertir
    movwf    INDF
    incf    FSR
, f
    return
    
;******************************************************************
;
                         ROUTINE DE TEMPORISATION
;******************************************************************
;
 Cette routine introduit un retard de environ w secondes
; pendant lequel l'affichage courant est maintenu si l'IT Timer0
; est active. wait_temp est décrémenté dans cette IT.
wait
    movwf    wait_temp
wait_1
    movf    wait_temp
, f
    btfss    STATUS
,Z
    goto    wait_1
    return
        
; initialise le tampon pour la phase de test d'affichage
; tous les segment et le point doivent s'
allumer    
Tests_Affichage    
    call    RemplirTamponAvec_8
    movlw    .2
    call    wait
    return

;******************************************************************
;
                 Routines de remplissage du tampon
;******************************************************************
RemplirTamponAvec_chiffreVide
    movlw    chiffreVide
    goto    RemplirTampon
RemplirTamponAvec_tiretB
    movlw    tiretB
    goto    RemplirTampon
RemplirTamponAvec_tiretM
    movlw    tiretM
    goto    RemplirTampon
RemplirTamponAvec_tiretH
    movlw    tiretH
    goto    RemplirTampon
RemplirTamponAvec_8
    movlw    chiffre8
    ADD_POINT
RemplirTampon
    movwf    RemplirTampon_temp
    movlw    MPX_Tampon
    movwf    FSR
    movlw    NbAfficheurs
    movwf    cmpt_remplirTampon
    movf    RemplirTampon_temp
, w
RemplirTampon_1
    movwf    INDF
    incf    FSR
,f
    decfsz    cmpt_remplirTampon
, f
    goto    RemplirTampon_1
    return
Fin_Code
    
    
; introduire le code des deux modules utilisés
    MPX_CODE
    org    0x200    
; pour assurer que le code de DCF77 soit dans une
                
; seule page
    DCF77_CODE

    END
Cordialement

JJE

C'est pas parcequ'on n'a rien à dire qu'il faut fermer sa G....e

Retourner vers « Langage ASM »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 5 invités