.Title r11c3.asm jdn981126 000118 0123 Attention vérifier Bitrate et 27512/128 \titre;R11c3.asm .Proc M6811 ; Déclare les instructions .Ref HC11F1 ; Déclare les adresses internes du HC11 et les bits .Ins R11c3Def.asi ; I/O .Ins R11c3Var.asi Prom512 = 0 ; si =0 27128 ou Simprom RokAf = 0 ; si =1, compatible RokAf, mais plus de plus de test 0 avec Mubus Bitrate = (2**SCP1)+(2**SCP0) ; Quartz SO80 8MHz, 9600 bits/s ; Bitrate = 0 ; Quartz SO73 7,3.. MHz, 115'200 bits/s \b;Le contenu de la mémoire morte .If Prom512 ; Pour 27512 .Loc 16'0000 ; On remplit toute la ROM avec FF .Fill.8 2**16,-1 ; pour accélérer la programmation .Else ; Pour 27128 et Simprom .Loc 16'C000 .Fill.8 2**14,-1 .Endif .Loc 16'C000 ; Adresse pour le début du programme .ASCII "R11c3 80" .ASCII "Day<"0"+(sysdate/(2**4).and.16'F)><"0"+(sysdate.and.16'F)>/" .ASCII "<"0"+(sysdate/(2**12).and.16'F)><"0"+(sysdate/(2**8).and.16'F)>" .ASCII "Tim<"0"+(systime/(2**20).and.16'F)><"0"+(systime/(2**16).and.16'F)>:" .ASCII "<"0"+(systime/(2**12).and.16'F)><"0"+(systime/(2**8).and.16'F)>" .32 Sysdate,Systime ; Systime et sysdate sont des variables BCD 32 bits. L'année n'est pas affichée \titre;Programme principal \prog:Init et choix d'un test| Deb: Move #InitPos,A Move A,InitRz ; configure le mapping mémoire MinSpeed = 16 ; prediv 1 (11 si prediv par 4) Move #2'00,A ; Prédivise par 1 (inter PWM trop fréquentes autrement) Move A,TMSK2 Move #Pile,SP ; initialise la pile Move #MoCSCTL,A ; Adresse EPRom et Mubus Move A,CSCTL Move #MoCSGSIZ,A ; Sélection RAM dans trous Move A,CSGSIZ Move #MoDDRA,A ; initialise le port A Move A,DDRA Move #InitA,A Move A,PortA Move #MoDDRD,A ; initialise le port D Move A,DDRD Move #InitD,A Move A,PortD Move #MoDDRG,A ; initialise le port G Move A,DDRG Move #InitG,A Move A,PortG Clr EnMultSPI J$: Move Mubus,A .If RokAf Jump,NE N$ ; Le test 0 Mubus n'est plus valable Call IniSPI x$: Bic #2**bSel3,PortG Move A,SPDR W$: Test SPSR ; transfert pour lire Jump,PL W$ Move SPDR,A ; lit le registre Bis #2**bSel3,PortG Bic #2**bSel3,PortG ; Echo Move A,SPDR V$: Test SPSR ; transfert des bits Jump,PL V$ ; attend que le transfert soit terminé Bis #2**bSel3,PortG .Endif N$: Move A,Mubus Move A,B Move #TableSauts,IX Comp #NoMax,B ; Numéro de test maximum Jump,HS NoTest SL B ; Multiplie par 2 Add B,IX ; Ajoute à IX Move {IX},IX ; Prends l'adresse de saut Jump {IX} ; Effectue le saut calculé Notest: Call Beep ; bip-bip si le test n'existe pas Call Delay1s Inc B Move B,Mubus Jump Notest TableSauts: .16 Test0, Test01, Test2, Test3, Test4, Test5, Test6, Test7 .16 Test8, Test9, TestA, TestB, TestC, TestD, TestE, TestF .16 Test10, Test11, Test12, Test13, Test14, Test15, Test16, Test17 .16 Test18, Test19, Test1A, Test1B, Test1C, Test1D, Test1E, Test1F .16 Test20, Test21, Test22, Test23, Test24, Test25, Test26, Test27 .16 Test28, Test29, Test2A, Test2B, Test2C, Test2D, Test2E, Test2F .16 Test30, Test31, Test32, Test33, Test34, Test35, Test36, Test37 .16 Test38, Test39, Test3A, Test3B, Test3C, Test3D, Test3E, Test3F NoMax = (APC-TableSauts)/2 \colleplan 0mm:rok11cv \prog:Tests| \module:Test0|echo Mubus et lit PortE, buzz si 0 Test0: L$: Move PortE,B Move B,Mubus+1 Move Mubus,B ; voir le signal P Move B,Mubus Jump,NE L$ Inc A Jump,NE L$ Not PortD Jump L$ \module:Test01|Lit les ports A et G, initialisés en entrée Test01: Clr DDRG ; Tout en entrée sur G L$: Move Mubus,A Move A,PortA ; Excite moteurs si 10xxx et 0010x Move PortA,A ; Lit les encodeurs moteurs Move A,Mubus Move PortG,B ; voir détecteurs obstacles Move B,Mubus+1 ; et direction des roues ! Jump L$ \module:Test2|Clignote à 1Hz les ports PA PD PG (initialisés en sortie) et Mubus. Montre PA sur Mubus+1 Test2: Move #-1,A Move A,DDRD Move #2'10101010,A L$: Move A,Mubus Move A,PortA Move A,PortD Move A,PortG ; sentir et écouter haut-parleur Move PortA,B Move B,Mubus+1 Not A Call Delay1s Jump L$ \module:Test3|Fait tourner les moteurs, codage direct Test3: L$: Move Mubus,A ; lecture des interrupteurs Move A,Mubus ; echo sur mubus Move A,PortA Move PortA,A Move A,Mubus+1 Jump L$ \module:Test4|Moteurs à vitesse variable sur Mubus 1-255, f=~1,5kHz Test4: L$: Move Mubus,A Jump,NE N$ Inc A N$: Move A,C1 Neg A Move A,C2 ; Complément Move #DirR+DirL,A Move A,PortA ; Démarre A$: Dec C1 Jump,NE A$ Clr PortA ; Stoppe B$: Dec C2 Jump,NE B$ Jump L$ \module:Test5|Aller et retour et rotations du robot Test5: Call Delay1s Move #2'01010000,A Move A,PortA Move A,Mubus Move #5000,IY Call Delay Clr PortA Move A,Mubus Call Delay1s Move #2'10100000,A Move A,PortA Move A,Mubus Move #5000,IY Call Delay Clr PortA Move A,Mubus Call Delay1s Move #2'10010000,A Move A,PortA Move A,Mubus Move #5000,IY Call Delay Clr PortA Move A,Mubus Call Delay1s Move #2'01100000,A Move A,PortA Move A,Mubus Move #5000,IY Call Delay Clr PortA Move A,Mubus ; on pourrait éventuellement boucler Jump NoTest \module:Test6|Lecture convertisseur ; canal selon adresse sur Mubus, affiché sur Mubus+1 Test6: Bis #2**ADPU,Option ; Mets en service le convertisseur L$: Move Mubus,A Move A,Mubus And #2'1111,A Move A,ADCTL ; Mode Single channel, no scan 00000xxx A$: TestJump,EQ #2**CCF,ADCTL,A$ ; On attends la fin de la conversion Move ADR1,A Move A,Mubus+1 Jump L$ \module:Test7|Conv AD PE6 PE7 sur Mubus, Mubus+1 Test7: Bis #2**ADPU,Option ; Enable converter Move #2**Scan+2**Mult+4,B ; Multiple scan continu AN4..AN7 Move B,ADCTL ; Start conversion A$: TestJump,EQ #2**CCF,ADCTL,A$ ; ??? necc L$: Move ADR1,A ; Le résultat est dans ces registres Move ADR2,B Move AB,Mubus Jump L$ \module:Test8|Test types de zones mémoire. Mubus= adresse page ; on écrit 10101010 01010101 et on relit la meme chose en RAM, ; relit des 0 avec le teseur Mubus (bus non flottant?) Test8: Move #16'AA55,IY L$: Move Mubus,A Move #10,B Ex AB,IX ; Adresse Move IY,{IX} Move {IX},AB Move AB,Mubus Jump L$ \module:Test9|Test série sans PC: relier pin 2 et 3. Compte Test9: Call Iniserie Clr B L$: Inc B Move B,A Move B,Mubus Call PutByte Call GetByte Move A,Mubus+1 Move #100,IY Call Delay Jump L$ \module:TestA|Test echo série ; Envoie l'alphabet et un CR-LF, affiche Mubus ce qui est recu TestA: Call IniSerie Clr C1 l$: move #"Z"-" ",B ; nombre de caractères à envoyer move #" ",A ; le premier est un SPACE m$: call PutByte ; envoie le byte inc A ; dec B ; prochain caractère jump,ne m$ ; move #16'0D,A ; CR terminal call PutByte ; envoie le byte move #16'0A,A ; LF terminal call PutByte ; envoie le byte Move C1,A Move A,Mubus jump l$ \module:TestB|Test echo inversé ; Renvoie ce qui est recu TestB: Call IniSerie l$: Call GetByte ; attend un caractère sur l'USART Call PutByte ; echo sur le smaky Move A,Mubus ; copie sur Mubus Jump l$ \module:TestC|Transfert série par interruption TestC: Clr C1 Clr C2 Call IniISCI J$: ; Move C1,A ; Move A,Mubus ; echo sur mubus Jump J$ \module:TestD|Répétition d'une ligne tapée au clavier TestD: Call IniSerie L$: Call AfTim .Asciz "Tapez une ligne terminée par CR" Move #TaPix,IX Move #60,B ; Max 102= long table pixels Call GetLine Call AfText Jump L$ \module:TestE|Lit Mubus, si nouvelle valeur, envoie en BCD sur terminal TestE: Call IniSerie L$: Move Mubus,A Comp B,A Jump,EQ L$ Move A,B ; Nouvelle valeur de réf. Call AfADec Move #" ",A Call PutByte ; Un espace pour séparer Jump L$ \module:TestF|Test différents bit rate Mubus --> reg Baud ; Envoie l'alphabet et un CRLF ; 8 MHz 16'30 --> 9'600 bits/s ; 7.3.. MHz 16'10 --> 38'400 b/s 16'11 --> 19'200 b/s 16'12 --> 9'600 b/s ; 16'0 --> 115'200 b/s 16'1 57'600 b/s TestF: Move #(2**TE)+(2**RE),A Move A,SCCR2 ; active l'émetteur et le récepteur L$: Move Mubus,A Jump,PL L$ ; On envoi seulement si bit7 = 1 Move A,Baud ; F max Clr C1 move #"Z"-" ",B ; nombre de caractères à envoyer move #" ",A ; le premier est un SPACE m$: call PutByte ; envoie le byte inc A ; dec B ; prochain caractère jump,ne m$ ; move #16'0D,A ; CR terminal call PutByte ; envoie le byte move #16'0A,A ; LF terminal call PutByte ; envoie le byte Move C1,A jump l$ Jump Notest \module:Test10|Timer Test10: \b; Timer, on copie le compteur L$: Move TCnt,AB Move AB,Mubus Jump L$ \module:Test11|Réserve Test11: Jump Notest \module:Test12|Timer overflow Test12: Clr A Move A,Mubus+1 L$: Test TFlg2 Jump,Pl L$ Inc A Move A,Mubus+1 ; Overflow, on incrémente Bis #2**TOF,TFlg2 ; Service Jump L$ \module:Test13|Timer overflow by interrupt Test13: Clr A Move A,C1 ; Save in variable C1 Move A,Mubus+1 ; Display Move #2**TOI,A ; Autorisation locale Move A,TMsk2 ION Move #1,B Move #0,IX L$: Inc IX ; Waiting loop Jump,NE L$ Move B,Mubus ; Increment in main program RLC B ; Carry is not modified by the loop or by the interrupt Jump L$ ; so we will not loose the rotating bit IntTOF: Move C1,A ; All registers are saved on stack Move A,Mubus+1 Inc C1 Move #2**TOF,A ; Do not use a Bis instruction ! Move A,TFlg2 ; Service RetI \module:Test14|Test PWM, vitesse sur Mubus période 120 us, distance gauche affichée ; durée inter env 75 à 80 us ; 0, 1 ... 7E, 7F, 80, 81, .. FF ; Off Min Max Max Min Test14: Call IniPwm L$: Move DistL,AB Move AB,Mubus Move Mubus,A Move A,SpeedL Move A,SpeedR ; min 11 Call UpdatePwm Move #10,IY ; 10 ms Call Delay ; No reason to do it too frequenttly Jump L$ \module:Test15|Test PWM, vitesse sur Mubus période 120 us, ; valeur abs Vitesse G+D affichée ; 0, 1 ... 7E, 7F, 80, 81, .. FF ; Off Min Max Max Min Test15: Call IniPwm Call IniRTI L$: Move MSpeedL,AB Test B Jump,PL S$ Not B S$: Move B,Mubus Move MSpeedR,AB Test B Jump,PL T$ Not B T$: Move B,Mubus+1 Move Mubus,A Move A,SpeedL Move A,SpeedR ; min 20 Call UpdatePwm Move #10,IY ; 10 ms Call Delay ; No reason to do it too frequenttly Jump L$ \module:Test16|Test PWM 2 moteurs par interruption, vitesse selon 2 pot P1, P2 sur PE0, PE1 Test16: Bis #2**ADPU,Option ; Enable converter Move #2'00110000,B ; Multiple scan continu AN4..AN7 Move B,ADCTL ; Start conversion Call IniPwm L$: Move Adr1,A ; 1st pot Left Sub #16'80,A ; Vitesse nulle au milieu SL A ; Double Jump,VS Bl$ SL A ; Double Jump,VS Bl$ SL A ; Again Bl$: Jump,VC Cl$ ; Butées si dépassement Jump,Pl Dl$ Move #16'7F,A Jump Cl$ Dl$: Move #16'80,A Cl$: Move A,SpeedL Move A,Mubus Move Adr2,A ; 2e pot Right Add #16'80,A SL A ; Double Jump,VS Br$ SL A ; Double Jump,VS Br$ SL A ; Again Br$: Jump,VC Cr$ Jump,Pl Dr$ Move #16'7F,A Jump Cr$ Dr$: Move #16'80,A Cr$: Move A,SpeedR Move A,Mubus+1 Call UpdatePwm Move #10,IY ; 10 ms Call Delay ; No reason to do it too frequently Jump L$ \module:Test17|Same as 16, but M1 = P1+P2, M2 = P1-P2 Test17: Bis #2**ADPU,Option ; Enable converter Move #2'00110000,B ; Multiple scan continu AN4..AN7 Move B,ADCTL ; Start conversion Call IniPwm L$: Move Adr1,A ; 1st pot Left Sub #16'80,A ; Vitesse nulle au milieu SL A ; Double Jump,VS Bl$ SL A ; Double Jump,VS Bl$ SL A ; Again Bl$: Jump,VC Cl$ ; Butées si dépassement Jump,Pl Dl$ Move #16'7F,A Jump Cl$ Dl$: Move #16'80,A Cl$: Move A,SpeedL Move A,SpeedR Move A,Mubus Move Adr2,A ; 2e pot Right Add #16'80,A SL A ; Double Jump,VS Br$ SL A ; Double Jump,VS Br$ SL A ; Again Br$: Jump,VC Cr$ Jump,Pl Dr$ Move #16'7F,A Jump Cr$ Dr$: Move #16'80,A Cr$: Move A,B Move A,Mubus+1 Add SpeedR,B Jump,VC Er$ Jump,Pl Fr$ Move #16'7F,B Jump Er$ Fr$: Move #16'80,B ER$: Move B,SpeedR Sub SpeedL,A Jump,VC Gr$ Jump,Pl Hr$ Move #16'7F,A Jump Gr$ Hr$: Move #16'80,A Gr$: Move A,SpeedL ; Move AB,Mubus ; If you prefer to see the real speed of both motors Call UpdatePwm Move #10,IY ; 10 ms Call Delay ; No reason to do it too frequently Jump L$ \module:Test18|Odometry of left motor (J1) Test18: Call IniPwm L$: Move DistL,AB Move AB,Mubus Move SensL,A Move A,PortD Jump L$ \module:Test19|Odometry of right motor (J2) Test19: Call IniPwm L$: Move DistR,AB Move AB,Mubus Move SensR,A Move A,PortD Jump L$ \module:Test1A|Odometry on PC screen every sec Test1A: Call IniSerie Call IniPWM L$: Move #Tx1,IX Call AfText Move DistR,AB Move AB,Mubus Call AfxAB Call AfText ; on pointe déjà ce 2e texte Move DistL,AB Call AfxAB Call Delay1s Jump L$ Tx1: .Asciz "Right= " .Asciz " Left= " \module:Test1B|Echo data and messages \mod:{TaPix} Test1B: Call IniSerie L$: Call AfTim .Asciz "Your message: " Move #100,B Move #TaPix,IX Call GetLine Move #TaPix,IX Call AfText Call AfTim .Asciz "Your 4-digit hex number: " Call GetxAB Call AfxAB Jump L$ \module:Test1C|Test de toutes les interruptions PWM+Servo+Camera Test1C: Call IniPWM Call IniRTI ; L$: Move #40,A Move A,SpeedL Move A,SpeedR Call UpdatePWM L$: Move #300,AB Move AB,DurServo Move Mubus,A Move A,TempsIntegr Move Moyenne,A Move TSL250,B Move AB,Mubus Jump L$ \module:Test1D| Test1D: Call IniRTI Move #1,A Move A,TempsIntegr L$: Move Moyenne,A Move TSL250,B Move AB,Mubus Jump L$ \module:Test1E| Arrêt sur position Test1E: VitNom = 16'7F ; Max positif Distfrein = VitNom/4 ; il faudrai séparer distfrein et vitesse nominale. ; La distance frein est 2, 4, 1/2 fois la vitesse nominale Call IniPWM Call IniRTI V$: Move #VitNom,A ; Move Mubus,A W$: Move A,SpeedR Call UpdatePWM L$: Move DistR,AB Move AB,Mubus Move Mubus,A Clr B Sub DistR,AB Jump,Eq Stop$ Add #1,AB Jump,EQ Stop$ Sub #1,AB Jump,Mi Back$ Forw$: Comp #Distfrein,AB Jump,LO Ass$ Move #VitNom,B Jump F$ Back$: Comp #-Distfrein,AB Jump,GT Ass$ Move #-(VitNom+1),B Jump F$ Ass$: ASR B ASR B Jump F$ Stop$: Clr B F$: Move B,SpeedR Call UpdatePWM Jump L$ \module:Test1F|Lecture SPI, pour PSD, conv en BCD 00-99 Test1F: Move #SPIIntOff,A Move A,SPCR ; On envoie la valeur lue sur Mubus, ce qui est lu va sur Mubus+1 L$: Move Mubus,A Move A,Mubus Bic #2**BSel3,PortG ; SPI J9 Move #14,B ; 50 \mu;s X$: Dec B Jump,NE X$ Move A,SPDR W$: TestJump,EQ #2**SPIF,SPSR,W$ ; On attend la fin de la transmission Move SPDR,A Bis #2**BSel3,PortG Call BinBCD Move A,Mubus+1 Move #200,A A$: Dec A ; Petite attente 500 us pour l'oscillo Jump,NE A$ Jump L$ BinBCD: ; Routine naive lente et pas optimisée \in:A \out:A Move A,B Clr A L$: Test B Jump,EQ F$ Add #1,A DAA A Dec B Jump L$ F$: Ret \module:Test20|Transfert SPI programmé sur J8 \b;Lent pour PIC, avec pause 5\mu;s \S:Sel|-->Ck SPIIntOff = 2'01010011 ; Master, ...Voir doc Motorola Test20: Move #SPIIntOff,A Move A,SPCR ; On envoie la valeur lue sur Mubus, ce qui est lu va sur Mubus+1 L$: Move Mubus,A Move A,Mubus Bic #2**BSel3,PortG ; SPI J9 Move #14,B ; 50 \mu;s X$: Dec B Jump,NE X$ Move A,SPDR W$: TestJump,EQ #2**SPIF,SPSR,W$ ; On attend la fin de la transmission Move SPDR,A Bis #2**BSel3,PortG Move A,Mubus+1 Move #200,A A$: Dec A ; Petite attente 500 us pour l'oscillo Jump,NE A$ Jump L$ \module:Test21|Transfert SPI par interruption \b;Lent pour PIC, avec pause 50\mu;s \S:Sel|-->Ck SPIIntOn = 2'11010011 ; 62 kHz 16\mu;s periode Test21: Move #ISPI21,IX Move IX,AdISPI ION L$: Move #1,IY Call Delay ; 4 envois toutes les ms Move PortD,A Xor #2**1,A Move A,PortD ; Clignote lampe verte Bic #2**BSel3,PortG ; \S:Sel| actif sur SPI J9 Move #14,A ; 50 \mu;s X$: Dec A Jump,NE X$ Move Mubus,A Move A,SPDR ; Lance le premier transfert Move #SPIIntOn,A ; Vitesse max, Ion local Move A,SPCR Jump L$ \b;Routine inter SPI affiche sur mubus+1 ISPI21: Move #SPIIntOff,A Move A,SPCR ; Désactiver les inter locales Test SPSR ; Clear SPIF ;; ION ; Remettre au plus vite pour le PWM Move SPDR,A ; On lit Move A,Mubus+1 Bis #2**BSel3,PortG RetI \module:Test22|Transfert SPI tableau de 2x2 bytes en Tapix: Test22: Call IniPWM Call IniRTI Move #16'11,A Move A,EnMultSPI Move #ISPI22,IX Move IX,AdISPI Move #TaVarSPI+(2*2),AB ; test avec 2 reg SPI Move AB,FinTaVarSPI Move #TavarSPI,IX L$: Move {IX},AB Move AB,Mubus Move Mubus,A Move A,{IX} Move A,{IX}+1 Jump L$ \b;Routine d'interruption Le RTI lance le premier transfert ISPI22: ; Routine d'interruption SPI Move #SPIIntOff,A Move A,SPCR ; Désactiver les inter locales Test SPSR ; Clear SPIF ION ; Permettre le PWM Move SPDR,A ; On lit Move PtVarSPI,IX Move A,{IX} Inc IX Comp FinTaVarSPI,IX Jump,EQ F$ Move {IX},A Move A,SPDR ; Relance le transfert série Inc IX Move IX,PtVarSPI Move #SPIIntOn,A ; Vitesse max, Ion local Move A,SPCR ; On aura un interrupt en retour RetI F$: Bis #2**BSel3,PortG ; \S:Sel| = 1 RetI ; C'est fini pour un instant \module:Test23|Transfert par interruption 1-8 bytes adaptatif ; Il faut que la chaine SPI soit fermée. ; Mubus adresse canal sélectionné pour aff. Mubus<7> bloque le compteur envoyé Test23: MaxByteSPI = 8 ; On envoie 8 mots pour vider les registres SPI Move #SPIIntOff,A Move A,SPCR Move #MaxByteSPI,A Move A,C1 Bic #2**BSel3,PortG ; SPI J9 Move #14,B ; 50 \mu;s X$: Dec B Jump,NE X$ L$: Clr A Move A,SPDR ; On envoie V$: TestJump,EQ #2**SPIF,SPSR,V$ ; On attend la fin de la transmission Dec C1 Jump,NE L$ ; Une petite attente pour l'oscillo Move #14,B ; 50 \mu;s Y$: Dec B Jump,NE Y$ ;On envoie un motif et on attend de le retrouver Motif = 2'11001000 Move #Motif,A Move #-1,B ; 2 transferts pour récupérer le premier M$: Move A,SPDR ; On écrit A (motif la première fois) W$: TestJump,EQ #2**SPIF,SPSR,W$ ; On attend la fin de la transmission Inc B Comp #MaxByteSPI+1,B Jump,EQ ErrSPI ; circuit pas femé ou trop long Move SPDR,A ; Recu? Comp #Motif,A Jump,NE M$ ; On initialise la fin selon longueur dans B Move #TaVarSPI,IX SL B ; x2 Add B,IX Move IX,FinTaVarSPI Bis #2**BSel3,PortG ; On lance le transfert par interruption Call IniPWM Call IniRTI Move #16'11,A Move A,EnMultSPI Move #ISPI22,IX Move IX,AdISPI ; On lit Mubus pour décider ce qu'on affiche en 8 bits ; Mubus<7> bloque le compteur envoyé sur le canal sélectionné Bcle: Move Mubus,A Move A,B And #2'111,B SL B ; x2 Move #TaVarSPI,IX Add B,IX ; Pointe le reg W ; Compteur 16 bits dans IY blocable si Mubus:#7 = 1 Test A Jump,MI N$ Inc IY N$: ; On lit et affiche sur Mubus+1 Move {IX}+1,A Move A,Mubus+1 ; On écrit le compteur IY dans le registre SPI sélectionné Ex AB,IY Move A,Mubus Move A,{IX} Ex AB,IY Jump Bcle ErrSPI: Move #16'55,A Move A,Mubus+1 Jump Notest \module:Test24|Test I2C Interf parallele - ecriture valeur sur Mubus P8574 = 16'40 Test24: L$: Call Start Move #P8574+W,A Call Write Call GetAck Move Mubus,A Call Write Call GetAck Call Stop Move #14,A ; 50 \mu;s X$: Dec A Jump,NE X$ Jump L$ \module:Test25|Test affichage 3x12 EA7123 Ad7123 = 16'74 Control = 16'0 Function = 16'20 DisOnNC = 16'C ; No cursor DisOnC = 16'D ; gros cursor EntryMode = 6 StartData = 16'40 Test25: Call Start Move #Ad7123+W,A Call Write Call GetAck Call D20 Move #TxAfOrd,IX O$: Move {IX},A ; Terminateur -1 Inc A Jump,EQ F$ Dec A Inc IX Call Write Call GetAck Call D20 Jump O$ Call Stop Call D20 Call Start Move #Ad7123+W,A Call Write Call GetAck Call D20 Move #StartData,A Call Write Call GetAck Call D20 ; on peut envoyer le data Move #TxAfi2c,IX L$: Move {IX},A Jump,EQ F$ Inc IX Call Write Call GetAck Call D20 Jump L$ F$: Call Stop Jump APC D20: ; délai 20 \mu;s Push A Move #8,A X$: Dec A Jump,NE X$ Pop A Ret TxAfOrd: .8 Control,Function,DisOnC,EntryMode,-1 TxAfI2C: .Asciz " LAMI Rok11 123456789012abcdefghijkl" \module:Test26|Test RAM I2C 8583 8570 RamI2C = 16'A0 Test26: L$: Call Start Move #RamI2C+W,A Call Write Call GetAck Move #16'11,A ; Adresse dans la RAM Call Write Call GetAck Move Mubus,A ; Data Call Write Call GetAck Call Stop Nop Nop Nop Call Start Move #RamI2C+W,A Call Write Call GetAck Move #16'11,A ; Adresse Call Write Call GetAck Call Restart Move #RamI2C+R,A Call Write Call GetAck Call Read Call GiveNAck Call Stop Move A,Mubus ; Lit le Data Jump L$ \module:Testxx|Module Affichage Meier: Compte Aff+ Mubus et lit les inter --> Mubus+1 Aff = 16'38 ;;Test26: ;; L$: ; on écrit un compteur Call Start Move #Aff+W,A Call Write Call GetAck Move #"b",A Call Write Call GetAck Inc IX Push IX Pop A Pop B Move A,Mubus Call Write Call GetAck Call Stop Nop Nop ;Un peu d'attente pour mieux voir à l'oscillo Call Start Move #Aff+W,A ; Sélection adresse Call Write Call GetAck Move #"s",A ; Ordre Call Write Call GetAck Call ReStart Move #Aff+R,A ; Resélection Call Write Call GetAck Call Read Move A,Mubus+1 Call GiveNAck ; GiveNack Call Stop Jump L$ \module:Test27|Module PSD Meier: Lecture distance Test27: L$: Call Start Move #Aff+W,A ; Sélection adresse Call Write Call GetAck Move #"a",A ; Ordre Call Write Call GetAck Call ReStart Move #Aff+R,A ; Resélection Call Write Call GetAck Call Read Move A,Mubus+1 Call GiveNAck ; GiveNack Call Stop Jump L$ \module:Test28|Lecture caméra sans stockage. Observation à l'oscillo. ; Balayage environ 1ms, attente Mubus*300 microsec (0.3ms à 27ms) entre balayages Test28: Loop$: Bis #2**bSI,PortG ; Flanc montant du SI, donc préparation au démarrage de la lecture Bis #2**bCLK,PortG ; Flanc montant clock et démarrage de la lecture Move #102,B L$: Bic #2**bSI+2**bCLK,PortG ; Flanc descendant clock et confirme SI à zero Bis #2**bCLK,PortG ; Flanc montant du clock Dec B ; On décrémente Jump,NE L$ ; On sort de la boucle après avoir lu les 102 pixels Bic #2**bCLK,PortG ; Hologe au repos Move Mubus,A Clr B Ex AB,IY W$: Dec IY Nop Jump,NE W$ Jump Loop$ \module:Test29|Lit 102 pixels, temps intégration selon Mubus (1 à 255 ms) \b;TSL250/252 sur Mubus, Moyenne sur Mubus+1 Test29: Bis #2**ADPU,Option ; Mets en service le convertisseur du port E Clr Mubus Clr Mubus+1 Loop$: Move #TaPix,IX Move Mubus,A Jump,Mi S34$ Call Scan102 Jump F$ S34$: Call Scan34 F$: Move B,Mubus ; Valeur TSL252/250 Move A,Mubus+1 ; Moyenne des 102 pixels Move Mubus,A ; Temps d'intégration Clr B Ex AB,IY W$: Dec IY Nop Jump,NE W$ Jump Loop$ \module:Test2A|Affichage sur Mubus selon seuil sur Mubus Test2A: Bis #2**ADPU,Option ; Mets en service le convertisseur du port E Clr Mubus Clr Mubus+1 Loop$: Move #TaPix,IX Move Mubus,A Jump,Mi S34$ Call Scan102 Jump F$ S34$: Call Scan34 F$: Move Moyenne,A Move TSL250,B Move AB,Mubus Move #TaPix+1,IX Move Mubus,B ; Seuil Call Af16M Jump Loop$ \module:Test2B|Affichage Mubus et lecture switch pour aff Mubus Test2B: Move #ModeSPI,A Move A,SPCR ; Registre de mode SPI L$: Move Mubus,A Move #TaPix,IX Move A,{IX} Move A,{IX}+1 Move A,{IX}+2 Not A Move A,{IX}+3 Call Af32 Move B,Mubus Jump L$ \module:Test2C|Affichage intensité variable Test2C: Move #ModeSPI,A Move A,SPCR ; Registre de mode SPI Move #0,B ; initialise le registre B L$: Move #TaIntensite,IX ; met le pointeur au début du tableau Move #Nbreboucles,B ; initialise le nbre de boucles à effectuer Move B,C1 A$: Call Af32 ; appelle la routine Affichage 32 bits Move A,Mubus Dec C1 Jump,NE A$ ; fait la boucle Nbreboucles fois Jump L$ ; on recommence Nbreboucles = 4 ; correspond au nbre de lignes du tableau TaIntensite: .Base 2 .8 00000000,00000011,11000000,00000000 ; le nombre de lignes .8 00000000,00001111,11110000,00000000 ; correspond au nombre de .8 00000000,11111111,11111111,00000000 ; seuils (cf microprojet .8 00001111,11111111,11111111,11110000 ; Gardiol/Harbi) .Base 10'10 \module:Test2D|Affichage hexa: compteur hexa Test2D: Move #ModeSPI,A Move A,SPCR ; Registre de mode SPI Clr D Clr E ; Compteur dans variable DE L$: Move Mubus,A ; Période comptage (poids fort de AB) B$: Dec B Jump,NE B$ Dec A Jump,NE B$ Move DE,AB Call AfHex Inc E Jump,NE N$ Inc D ; On affiche les poids forts Move D,A Move A,Mubus N$: Jump L$ \module:Test2E|Affichage hexa/BCD: compteur BCD Test2E: Move #ModeSPI,A Move A,SPCR ; Registre de mode SPI Clr D Clr E ; Compteur dans variable DE L$: Move Mubus,A ; Période comptage B$: Dec B Jump,NE B$ Dec A Jump,NE B$ Move DE,AB Call AfHex Move E,A Add #1,A DAA A Move A,E Jump,NE N$ Move D,A Add #1,A ; On affiche les poids forts DAA A Move A,D Move A,Mubus N$: Jump L$ \module:Test2F| Test2F: \module:Test30|Sharp par interruption (à faire) Test30: \module:Test31| Test31: Jump Notest \module:Test32|Caméra par interrupt avec servo qui bouge MinServo = 250 MaxServo = 1000 IncServo = (MaxServo-MinServo)/10 ; On veut faire 10 pas et revenir au début Test32: Call IniRTI Move #MinServo,AB Move AB,DurServo L$: Move Mubus,A Move A,TempsIntegr Move Moyenne,A move TSL250,B Move AB,Mubus ; Attente pour éviter des mises à jour trop fréquentes Move #500,IY ; 500 ms Call Delay Move #IncServo,AB Add DurServo,AB Comp #MaxServo,AB Jump,LO B$ Move #MinServo,AB B$: Move AB,DurServo Jump L$ \module:Test33|Caméra seule par interruptions Test33: Call IniRTI Move #4,A Move A,DurServo L$: Move Mubus,A Move A,TempsIntegr Move Moyenne,A move TSL250,B Move AB,Mubus ; Attente pour éviter des mises à jour trop fréquentes Move #200,IY Call Delay Jump L$ \module:Test34|Servo sur I2C/J6, pin3, longueur d'impulsion sur Mubus en 0.1 ms Test34: L$: Bis #2**Servo1,PortG Move Mubus,A Comp #20,A Jump,HS A$ Move #20,A A$: Move A,Mubus C$: Push IX ; environ 10us=0.01ms par boucle Pop IX Push IX Pop IX Nop Nop Dec A Jump,NE C$ Bic #2**Servo1,PortG Move #6000,IX ; Environ 20 ms D$: Dec IX Jump,NE D$ Jump L$ \module:Test35|Servo par interruption sur J6 pin 3 (PG1) ; Mubus=4 --> 0.5 ms =16'1F 4,5 ms Test35: Call IniRTI L$: Move Mubus,A And #2'11111,A Jump,NE M$ Inc A ; 0 pas admis M$: Clr B ; 1= 0.1 ms SR AB Move AB,DurServo ; ; Attente pour éviter des mises à jour trop fréquentes Move #20,IY Call Delay Jump L$ \module:Test36| Test36: \module:Test37| Test37: \module:Test38|Noyau temps réel Test38: \module:Test39| Test39: \module:Test3A| Test3A: \module:Test3B| Test3B: \module:Test3C|Saut en 16'1000 Test3C: Jump 16'1000 \module:Test3D|Saut en 16'4000 Test3D: Jump 16'4000 \module:Test3E|Chargeur S Test3E: Call ChargeurS Move A,Mubus+1 ; afficher l'erreur sur Mubus+1 Jump Notest .Ins R11c1ChS.asi \module:Test3F|Téléchargement format PDP11 Test3F: Call PDP11 Jump Notest ; on ne revient que s'il n'y a pas d'adresse de start \b;Erreurs (déclarées dans le fichier inséré) ; Er_Comp = -1 ; compteur > 256 ; Er_CBk = -2 ; erreur de cheksum dans le bloc ; Er_CLBk = -3 ; erreur de cheksum dans le dernier bloc .Ins R11c1Pdp.asi \module:Routines|de librairie \rout:Beep|Beep à env 3kHz pendant 0.1s \mod:F,A,IX \- Beep: move #500,IX M$: move PortD,A xor #2**BHP,A move A,PortD move #200,A ;demi-période N$: dec A jump,ne N$ dec IX ; beep length jump,ne M$ ret \rout:Delay1s|Retard env 1 seconde \rout:Delay|Retard en ~ms dans IY \mod;F,IY \- Delay1s: Move #1000,IY Delay: Push A M$: Move #250,A L$: Dec A Jump,NE L$ Dec IY Jump,NE M$ Pop A Ret \rout:IniSerie|Initialise le port série à 9600 b/s \mod;F, A \- IniSerie: Move #Bitrate,A Move A,Baud ; 9600 bauds Move #(2**TE)+(2**RE),A Move A,SCCR2 ; active l'émetteur et le récepteur Ret \rout:PutByte|Envoi un byte sur l'USART \in;A Byte à envoyer \mod;F, A \- PutByte: l$: TestJump,zs #(2**TDRE),SCSR,l$ ; on attend que l'émetteur soit vide Move A,SCDR ; envoie le byte Ret \rout;AfText|Envoie à l'USART un texte terminé par un zéro \in:IX pointeur début de texte \out;Pointe un texte suivant éventuel \mod;IX \- AfText: Push A L$: Move {IX},A Jump,EQ F$ Inc IX Call PutByte Jump L$ F$: Inc IX Pop A Ret \rout:AfTim|Affichage d'un texte qui suit immédiatement \mod;F \- AfTim: Push A Move F,A Push A IOFF ; Pas d'interrupt pendant que l'on manipule la pile Push IX Inc SP ; 4 bytes sur la pile Inc SP Inc SP Inc SP Pop IX ; Adresse de retour=pointeur texte L$: Move {IX},A Jump,EQ F$ Inc IX Call PutByte Jump L$ F$: Inc IX Push IX ; Adresse de retour après le texte Dec SP Dec SP Dec SP Dec SP Pop IX Pop A Move F,A ; Rétablit év les interruptions Pop A Ret \rout:AfxA|Affiche le contenu de A en Hexa \rout:AfxAB|Affiche AB (16 bits) en hexa \in:A,B \mod:F, C, DE \- AfxAB: Move AB,DE ; On sauve Call AfxA Move E,A Call AfxA Move DE,AB ; On rétablit Ret AfxA: Move A,C SR A SR A SR A SR A Call AfxNibble Move C,A And #2'1111,A Call AfxNibble Move C,A Ret \rout:AfxNible|Affiche 0-F en Ascii \in;A \mod;F,A \- AfxNibble: Comp #9+1,A Jump,LO N$ Add #"A"-"9"-1,A N$: Add #"0",A Call PutByte Ret \rout:AfADec|Converti binaire 0..255 en décimal Ascii 2-3 digits \in:A \mod;F, A \- AfADec: Push B Move A,B Sub #200,B Jump,LO C$ Move #"2",A Call PutByte ; Affiche le 2xx Jump D$ C$: Add #100,B Jump,HS D1$ Move #"1",A Call PutByte ; Affiche le 1xx Jump D$ D1$: Add #100,B Move #" ",A Call PutByte Comp #10,B Jump,HS D$ Move #" ",A Call PutByte Jump U$ D$: Clr A E$: Sub #10,B Jump,LO U1$ Inc A Jump E$ U1$: Or #"0",A ; A=nbre de dizaines Call PutByte Add #10,B ; B=reste=unités U$: Move B,A Or #"0",A Pop B Jump PutByte \rout:GetByte|Réception un byte sur l'USART \out;A Byte reçu \mod;F \- GetByte: l$: TestJump,zs #(2**RDRF),SCSR,l$ ; on attend que le recepteur soit plein Move SCDR,A ; lecture du byte Ret \rout:GetxA|Attend un chiffre hexa 8 bits terminé par un car non hexa \out;A chiffre hexa var C terminateur \mod;F, A, C, D \- GetxA: Clr D L$: Call GetByte Comp #"a",A Jump,LO M$ Sub #"a"-"A",A M$: Call PutByte Move A,C Sub #"0",A Jump,Mi F$ ; Inférieur à "0" Comp #10,A Jump,LO Ok$ ; Entre 0 et 9 Comp #"A"-"0",A Jump,LO F$ ; Entre "9" et "A" Sub #"A"-"9"-1,A Comp #16,A Jump,HS F$ ; Supérieur à "F" Ok$: Move A,C Move D,A ; Il y a év des poids archivés dans D SL A SL A SL A SL A Or C,A ; On ajoute à C --> D Move A,D Jump L$ F$: Move D,A Ret \rout:GetxAB|Attend un nbre hexa 16 bits \out:AB, Var C terminateur \mod;F, AB, C, DE \- GetxAB: Clr D Clr E L$: Call GetByte Comp #"a",A Jump,LO M$ Sub #"a"-"A",A M$: Call PutByte Move A,C Sub #"0",A Jump,Mi F$ ; Inférieur à "0" Comp #10,A Jump,LO Ok$ ; Entre 0 et 9 Comp #"A"-"0",A Jump,LO F$ ; Entre "9" et "A" Sub #"A"-"9"-1,A Comp #16,A Jump,HS F$ ; Supérieur à "F" Ok$: Move A,C Move DE,AB ; Il y a év des poids archivés dans DE SL AB SL AB SL AB SL AB Or C,B ; On ajoute à B --> DE Move AB,DE Jump L$ F$: Move D,A ; A écrasé par le der car Ret \rout:GetLine|Store a line terminated by CR or max in B, in memory (with echo) \in;IX pointeur texte à recevoir B longueur max non compris zero final \mod;F, A, B \- GetLine: Push IX L$: Call GetByte Call PutByte Move A,{IX} Move A,Mubus Inc IX Dec B Jump,EQ F$ Comp #CR,A Jump,NE L$ F$: Clr {IX} ; Terminateur de textes Pop IX Ret \rout:Scan102|Lecture des 102 pixels TSL1301, moyennés \in:IX zone de 102 pixels, Mubus= temps intégration \out:A=TSL250 valeur TSL250/252 B=Moyenne moyenne des 102 pixels lus \mod:A,B,IX,IY \- Scan102: Bis #2**bSI,PortG ; Flanc montant du SI, préparation au démarrage de la lecture Move #102,A Move A,C1 Move #0,IY L$: Bis #2**bCLK,PortG ; Flanc montant clock et lecture 1er pixel Move #2**Mult+4,A Move A,ADCTL ; Sélectionne les canaux 4..7 du port E Bic #2**bClk+2**bSI,PortG ; Flanc descendant clock et confirme SI=0 A$: TestJump,EQ #2**CCF,ADCTL,A$ ; On attends la fin de la conversion Move ADR3,B ; Le résultat est copié dans B Move B,{IX} Inc IX Add B,IY Dec C1 Jump,NE L$ Bic #2**bCLK,PortG ; Envoi d'un coup de clock suppl de fin Ex AB,IY ; Valeur à diviser par 102 Move #102,IX Div IX,AB,IX,AB ; AB/IX -> IX , reste dans AB ignoré Ex AB,IX ; Quotient dans B, A nul Move B,Moyenne Move ADR4,A ; Lecture TSL250 sur PE7 Move A,TSL250 Ret \rout:Scan34|Lecture des 102 pixels regroupés par 3 et moyennés (val 3/4) \in:IX zone de 34 pixels \out:A=TSL250 valeur TSL250/252 B=Moyenne moyenne des 102 pixels lus \mod:A,B,IX,IY, Somme \- Scan34: Clr Somme Clr Somme+1 Bis #SI,PortG ; Flanc montant du SI, préparation au démarrage de la lecture Move #102/3,A Move A,C1 W$: Bis #CLK,PortG ; Flanc montant clock et lecture 1er pixel Move #2**Mult+4,A Move A,ADCTL ; Sélectionne les canaux 4..7 du port E Bic #SI,PortG Bic #CLK,PortG ; Flanc descendant clock Move #0,IY A1$: TestJump,EQ #2**CCF,ADCTL,A1$ ; On attends la fin de la conversion Move ADR3,B ; Le résultat est copié dans B Add B,IY Bis #CLK,PortG ; Flanc montant du clock Move #2**Mult+4,A Move A,ADCTL ; Sélectionne le canal 0 du port E Bic #CLK,PortG ; Flanc descendant de la clock A2$: TestJump,EQ #2**CCF,ADCTL,A2$ Move Adr3,B ; Video sur PE6 Add B,IY Bis #CLK,PortG Move #2**Mult+4,A Move A,ADCTL Bic #CLK,PortG A3$: TestJump,EQ #2**CCF,ADCTL,A3$ Move Adr3,B Add B,IY Bis #CLK,PortG Add B,IY Push IY ;Move IY,AB Pop A ; Big endian Pop B SR AB SR AB ; Div par 4 pour simplifier Move B,{IX} Inc IX Ex AB,IY ; Move IY,AB Add Somme,AB Move AB,Somme Dec C1 Jump,NE W$ Bis #CLK,PortG ; Envoi d'un coup de clock suppl de fin Bic #CLK,PortG Move A,Moyenne Move ADR4,A ; Lecture TSL250 sur PE7 Move A,TSL250 Ret \rout:Aff16M|Affiche sur Mubus 32 pixels, 1 sur 2, ON si valeur >B \in:B seuil d'affichage IX pointeur table 32 pixels \mod:A,IX,IY \- Af16M: Move #0,IY Move #16,A Move A,C1 L$: Comp {IX},B Inc IX Inc IX ; 1 pixel sur 2 Ex AB,IY RLC B RLC A EX AB,IY Dec C1 Jump,NE L$ Move IY,Mubus Ret \rout:AfLin32|Affiche byte par 1 LED si valeur>B \in:B: Seuil IX:Pointe table de pixels (si 34, +1) \mod:A, IX, C1 \- AfLin32: Move #32,A Move A,C1 Bic #2**BSel3,PortG L$: Bic #2**bMoSi,PortD Comp {IX},B Inc IX Jump,HS C$ Bis #2**bMoSi,PortD C$: Bis #2**bCkSPI,PortD Nop Bic #2**bCkSPI,PortD Dec C1 Jump,NE L$ Bis #2**BSel3,PortG Ret \rout:Af32|Affichage 32 bits, transfert programmé avec SPI \in:IX pointe 4 byte, LSB first \out;A dernier mot de 8 bits lu \- \mod:F Af32: Bic #2**bSel3,PortG Call Af8 ; appelle la routine de chargement Move A,B Call Af8 ; des 4x8 bits en série Call Af8 Call Af8 Bis #2**bSel3,PortG ; impulsion du LD pour l'affichage des 32 diodes Ret \rout:Af8|Affichage 8 bits, transfert programmé avec SPI \in:IX Transfert 8 bits \mod:F,A \- Af8: Move {IX},A ; met la valeur pointée dans le registre A Inc IX ; avance le pointeur au bloc suivant Move A,SPDR W$: Test SPSR ; transfert des bits Jump,PL W$ ; attend que le transfert soit terminé Move SPDR,A ; lit le registre Ret \b;Routine Swap8, permute le mot de 8 bits dans A \in:A \mod;F,A Swap8: Push B Move #2'10000000,B ; Deviendra le Carry après 8 boucles L$: SL A RRC B Jump,CC L$ Move B,A Pop B Ret \rout:AfHex|Affiche AB en BCD \b;Ne converti pas de binaire en BCD! \in:AB \mod:F \- AfHex: Push IX Push B Push A Bic #2**BSel3,PortG Move B,A ; sauve poids forts And #2'1111,B Move #TaSeg,IX Add B,IX Move {IX},B Test SPSR ; clear Flag SPIF Move B,SPDR Nop ; Not required if Call Swap8 Nop Nop ; W$: TestJump,EQ #2**SPIF,SPSR,W$ ; slower than 3 Nop Move A,B SR B SR B SR B SR B Move #TaSeg,IX Add B,IX Move {IX},B Test SPSR ; clear Flag SPIF Move B,SPDR Nop ; Not required if Call Swap8 Nop Nop ; W$: TestJump,EQ #2**SPIF,SPSR,W$ ; slower than 3 Nop Pop A Push A ; Registre A Move A,B And #2'1111,B Move #TaSeg,IX Add B,IX Move {IX},B Test SPSR ; clear Flag SPIF Move B,SPDR Nop ; Not required if Call Swap8 Nop Nop ; W$: TestJump,EQ #2**SPIF,SPSR,W$ ; slower than 3 Nop Move A,B SR B SR B SR B SR B Move #TaSeg,IX Add B,IX Move {IX},B Test SPSR ; clear Flag SPIF Move B,SPDR Nop ; Not required if Call Swap8 Nop Nop ; W$: TestJump,EQ #2**SPIF,SPSR,W$ ; slower than 3 Nop Bis #2**BSel3,PortG Pop A Pop B Pop IX Ret TaSeg: .8 2'11111100 ; 0 .8 2'01100000 .8 2'11011010 ; 2 .8 2'11110010 .8 2'01100110 ; 4 .8 2'10110110 .8 2'10111110 ; 6 .8 2'11100000 .8 2'11111110 ; 8 .8 2'11110110 .8 2'11101110 ; A .8 2'00111110 .8 2'10011100 ; C .8 2'01111010 .8 2'10011110 ; E .8 2'10001110 ; Table inversée (à utiliser si transfert programmé) .8 2'00111111 ; 0 .8 2'00000110 .8 2'01011011 ; 2 .8 2'01001111 .8 2'01100110 ; 4 .8 2'01101101 .8 2'01111101 ; 6 .8 2'00000111 .8 2'01111111 ; 8 .8 2'01101111 .8 2'01110111 ; A .8 2'01111100 .8 2'01111001 ; C .8 2'01011110 .8 2'01111001 ; E .8 2'01110000 \macro;I2C| .Macro SetSDA ; Input BIC #2**SDA,DDRG .EndMacro .Macro ClrSDA ; Out zero BIS #2**SDA,DDRG .EndMacro .Macro SetSCK ; Input BIC #2**SCK,DDRG .EndMacro .Macro ClrSCK ; Out BIS #2**SCK,DDRG .EndMacro W = 0 R = 1 \rout;I2C| Di2c: Push IX ; Délai 10\mu;s Pop IX ; Push IX ; 17 us avec ces 2 instr ; Pop IX Ret Start: ClrSDA ; SDA '''\....... Call Di2c ClrSCK ; SCK '''''''\... ! >4 us Call Di2c Ret ReStart: SetSCk ; SCK ==/''' Call Di2c ClrSDA ; SDA ====\..... Call Di2c ClrSCK ; SCK '''''''\... ! >4 us Call Di2c Ret GetAck: SetSDA TestJump,BC #2**SDA,Not PortG,ErAck G: SetSCK Call Di2c ClrSCK Call Di2c Ret GetNack: SetSDA TestJump,BC #2**SDA,PortG,ErNack GN: SetSCK Call Di2c ClrSCK Call Di2c Ret ErAck: Move #16'51,A Move A,Mubus+1 Jump G Jump APC ; A redéfinir ErNack: Move #16'A2,A Move A,Mubus+1 Jump GN Jump APC ; A redéfinir GiveAck: ClrSDA Call Di2c SetSCK Call Di2c ClrSCK SetSDA Call Di2c Ret GiveNack: SetSDA Call Di2c SetSCK Call Di2c ClrSCK Call Di2c Ret Stop: ClrSDA ; SDA ==\....... Call Di2c SetSCK ; SCK ...../'''''' Call Di2c SetSDA ; SDA ......../''' Ret \rout:Write| \in;A byte to be transmitted \mod:- Write: Push A Push B Move #8,B L$: SL A Jump,CC Z$ SetSDA Jump N$ Z$: ClrSDA N$: Call Di2c SetSCK Call Di2c ClrSCK Dec B Jump,NE L$ SetSDA Pop B Pop A Ret \rout:Read| \out:A ; SDA =XX=====^========= \mod:A ; SCK \......./''''''\........ 5us 5/6\mu;s Read: Push B Move #8,B L$: Call Di2c SetSCK ClrC TestJump,EQ #2**SDA,PortG,Z$ SetC Z$: RLC A N$: Call Di2c ClrSCK Dec B Jump,NE L$ Pop B Ret ;------------------------------------------------- \rout:Interruptions| \rout:IniEncoder|Init rotary encoder on port A <3..0> \b;Appelé par IniPWM \mod;F,A,B IniEncoder: Move PortA,A ; Initial conditions Not A And #MaskOpto,A Move A,OldOpto Clr A Clr B Move AB,DistL Move AB,DistR Ret \rout:IniPwm|Lance l'interruption Toc1 qui définit la période PWM ; Period = 256 E-clock ; 4kHz (no predivisor) IniPwm: Clr A Clr B Move AB,Toc1 Inc Toc1 Move AB,Toc2 Move AB,Toc4 Move B,SpeedL ; Assigned speed = zero Move B,SpeedR Move #MaskOC1,A ; 4 bits updated at next interrupt Move A,OC1M Move #2**OM2+2**OM4,A ; Modes 10 and 11 Move A,TCTL1 Call UpdatePwm Call IniEncoder Move #2**OC1I,A ; Ready for interrupts Move A,TMSK1 ION Ret \rout:Encoder|René Sommer algorithm \in:DistL, DistR \out:idem, SensL, SensL \mod:F A B IX (saved by interrupt routine) Encoder: Move OldOpto,B Move PortA,A Not A And #MaskOpto,A Move A,OldOpto ; Prêt pour le prochain tour Move #SwapTable,IX Add B,IX Xor {IX},A ; entre X+ Y+ et Y X Move #RoutTable,IX Move A,B SL B ; x2 car table d'adresses 16 bits Add B,IX Move #-1,A ; Ready for possible negative direction Move {IX},IX Push IX Move DistL,IX Move DistR,IY Ret ; Final return done in the called routine IncL: Inc IX Clr SensL NoChange: End: Move IX,DistL Move IY,DistR Ret DecL: Dec IX Move A,SensL Jump End IncLR: Inc IX Clr SensL IncR: Inc IY Clr SensR Jump End IncLDecR: Inc IX Clr SensL DecR: Dec IY Move A,SensR Jump End DecLR: Dec IX Move A,SensL Dec IY Move A,SensR Jump End DecLIncR: Dec IX Move A,SensL Inc IY Clr SensR Jump End SwapTable: .8 2'00000000 .8 2'00000010 .8 2'00000001 .8 2'00000011 .8 2'00001000 ; 01xx .8 2'00001010 .8 2'00001001 .8 2'00001011 .8 2'00000100 ; 10xx .8 2'00000110 .8 2'00000101 .8 2'00000111 .8 2'00001100 ; 11xx .8 2'00001110 .8 2'00001101 .8 2'00001111 ; Result of the Xor operation with the swapped values ; 00 nochange 01 increment 10 decrement 11 no change RoutTable: ;Left-Right .16 NoChange ; 0000 .16 IncR ; 0001 .16 DecR ; 0010 .16 NoChange ; 0011 .16 IncL ; 0100 .16 IncLR ; 0101 .16 IncLDecR ; 0110 .16 IncL ; 0111 .16 DecL ; 1000 .16 DecLIncR ; 1001 .16 DecLR ; 1010 .16 DecL ; 1011 .16 NoChange ; 1100 .16 IncR ; 1101 .16 DecR ; 1110 .16 NoChange ; 1111 ; Fin routine Sommer \rout:UpdatePwm|Dans routine d'interruption \colleplan 0mm:rok1pwm UpdatePwm: Clr B ; Begin construction of OC1D ; Left motor Move SpeedL,A Jump,Mi BackL Jump,EQ Stop$ Comp #MinSpeed,A ; Minimum speed (response time interrupt routine) Jump,HS M$ Move #MinSpeed,A M$: Comp #127,A ; Max speed = full speed Jump,EQ Fast$ SL A ; Double: PWM ratio = <2..254>/256 Move A,Toc2+1 ; Update low digits Or #PwmL,B ; Pwml=1, DirL=1 Bic #2**OL2,TCTL1 ; PwmL passera à zero Jump DoRight Stop$: ; B = OC1D still zero Bic #2**OL2,TCTL1 ; PwmL will stay to zero Jump DoRight Fast$: ; Full forward left Or #PwmL,B ; PwmL=1, DirL=0 Bis #2**OL2,TCTL1 ; PwmL stay at 1 Jump DoRight BackL: Neg A ; Absolute value Comp #MinSpeed,A ; Minimum speed Jump,HS M$ Move #MinSpeed,A M$: Comp #128,A ; Max speed Jump,EQ FBack$ SL A ; Double: PWM ratio = <2..254>/256 Move A,Toc2+1 ; Update LSB Or #DirL,B ; PwmL=0, DirL=1 Bis #2**OL2,TCTL1 ; PwmL will go to 1 Jump DoRight FBack$: ; Full backward Or #DirL,B ; PwmL=0, DirL=1 Bic #2**OL2,TCTL1 ; PwmL stay at 0 ; End left DoRight: Move SpeedR,A Jump,Mi BackR Jump,EQ Stop$ Comp #MinSpeed,A ; Minimum speed (response time interrupt routine) Jump,HS M$ Move #MinSpeed,A M$: Comp #127,A ; Max speed = full speed Jump,EQ Fast$ SL A ; Double: PWM ratio = <2..254>/256 Move A,Toc4+1 ; Update low digits Or #PwmR,B ; PwmR=1, DirR=1 Bic #2**OL4,TCTL1 ; PwmR passera à zero Jump Go Stop$: ; B = OC1D still zero Bic #2**OL4,TCTL1 ; PwmR will stay to zero Jump Go Fast$: ; Full forward left Or #PWMR,B ; PwmR=1, DirR=0 Bis #2**OL4,TCTL1 ; PwmR stay at 1 Jump Go BackR: Neg A ; Absolute value Comp #MinSpeed,A ; Minimum speed Jump,HS M$ Move #MinSpeed,A M$: Comp #128,A ; Max speed Jump,EQ FBack$ SL A ; Double: PWM ratio = <2..254>/256 Move A,Toc4+1 ; Update LSB Or #DirR,B ; PwmR=0, DirR=1 Bis #2**OL4,TCTL1 ; PwmR will go to 1 Jump Go FBack$: ; Full backward Or #DirR,B ; PwmR=0, DirR=1 Bic #2**OL4,TCTL1 ; PwmL stay at 0 ; End Right Go: Move B,OC1D Ret \rout:IToc1|Timer 1 interrupt, every 250 us, duration 30 us ; Deactivation of Toc2 Toc4 after a min of 15 us (10 ck?) IToc1: Inc Toc2 Inc Toc4 Inc Toc1 ; Add rotary encoder wit R.Sommer algorithm ;Move A,Mubus+2 Call Encoder ; You may also do something else here every 250\mu;s Move #2**OC1F,A Move A,TFlg1 ; Clear flag ;Move A,Mubus+3 RetI \rout:IniRTI|Initialisation RTI et Toc3 pour Servo et Caméra ; Il faut des valeurs /= 0 pour que cela soit actif IniRTI: Bis #2**ADPU,Option ; Enable converter Clr A Move A,DurServo Move A,DurServo+1 Move A,TempsIntegr Inc A Move A,DecTempsIntegr Bis #2**RTR1,PACTL ; 10 16.4 ms Bis #2**RTII,TMSK2 Ion Ret \rout:Interrupt RTI|Real time 16ms ; Si le temps caméra est 0, elle est ignorée, si 1, le servo est ignoré ; Si DurServo = 0, ; Le servo n'est pas servi quand la caméra l'est IRTI: move A,mubus+2 Move 2**RTIF,A Move A,TFlg2 ; Clear flag RTIF ION ; pour le PWM ; On prépare le transfert SPI Test EnMultSPI Jump,EQ NS$ ; Pas de SPI multiple Bic #2**BSel3,PortG ; Sel3=0, attendre 50\mu;s avant le premier clock NS$: \b;On mesure la vitesse Move DistL,AB Sub OldDistL,AB ; Test A ; Si on veut raccourcir les vitesse sur 8 bits ; Jump,EQ Error Move AB,MSpeedL ; Measured speed Move DistL,AB Move AB,OldDistL Move DistR,AB Sub OldDistR,AB ; Test A ; Jump,EQ Error Move AB,MSpeedR ; Measured speed Move DistR,AB Move AB,OldDistR Test TempsIntegr Jump,EQ RTIServo Dec DecTempsIntegr Jump,NE RTIServo Move TempsIntegr,A Move A,DecTempsIntegr Move #TaPix,IX Call Scan34 move a,mubus+3 ;; mesure durée Jump FinRTI RTIServo: Move DurServo,AB Jump,EQ NoToc3 Bis #2**OC3I,TMSK1 Bis #2**Servo1,PortG Add TCNT,AB Move AB,Toc3 ; Timer not connected to PA5 FinRTI: ; On lance encore les transferts SPI Sel3 actif voir plus haut Test EnMultSPI Jump,EQ F$ Move #TaVarSPI,IX Move {IX},A Inc IX Move IX,PtVarSPI Move A,SPDR ; On lance le premier transfert Move #SPIIntOn,A ; Vitesse max, Ion local Move A,SPCR ; On aura des interruptS PI en retour F$: RetI NoToc3: Move #2**OC3F,A Move A,TFlg1 ; Clear flag utile ici? Bic #2**OC3I,TMSK1 Jump FinRTI \rout:Interrupt IToc3|Désactivation des servos IToc3: Bic #2**Servo1,PortG Move #2**OC3F,A Move A,TFlg1 ; Clear flag Toc3 dans IRTI ?? RetI \rout:IniISCI|Interrupt sur canal série, exemple avec echo \mod;F, A \- IniISCI: move #Bitrate,A move A,Baud move #2**RE+2**RIE,A ; interrupt en réception seulement move A,SCCR2 ; active l'émetteur et le récepteur en inter ION Ret ; Echo simple et compte les caractères ; Utilise C2 ISCI: Move SCSR,A ; On doit lire SCSR Move SCDR,A ; pour faire un clear de RDRF Move A,SCDR ; Renvoi immédiat, il y a év réception en // Move A,Mubus ; echo sur mubus Inc C2 Move C2,A Move A,Mubus+1 RetI \rout;ISPI indirection ISPI: Move AdISPI,IX Jump {IX} ; -------------------------------------------------- NoRout: Push B Push A Call Beep ; bip-bip si le test n'existe pas Move #300,IY Call Delay Pop A Pop B Move AB,Mubus ; affiche AB Jump NoRout \b;Les adresses de routines importantes référées par \b; les programmes téléchargés .Loc 16'FF80 ; Place pour routines Jump Beep Jump IniSerie Jump PutByte Jump AfxA Jump AfxAB Jump AfADec Jump AfText Jump AfTim ; 16'FF98 Jump GetByte Jump GetLine Jump GetxA Jump GetxAB Jump IniISCI Jump IniRTI Jump IniPWM ; Init Pwm and the encoder routine Jump UpdatePWM ; 16'FFB0 Jump Delay Jump Delay1s Jump Scan102 Jump Scan34 Jump Af8 Jump Af32 Jump AfHex Jump Af16M ; 16'FFC8 Jump AfLin32 .If APC .HS. 16'FFD6 .Error Dépassement, erreur adresse routines .Endif ; -------------------------------------------------- \b;Les vecteurs d'interruption et de démarrage .Loc 16'FFDE .16 IntTOF ; Timer overflow .Loc 16'FFD6 .16 ISCI ; Serial .Loc 16'FFD8 .16 ISPI ; DAC, display or other serial chip .Loc 16'FFE4 .16 IToc3 ; Timer 3 (servo deactivation) .Loc 16'FFE8 .16 IToc1 ; Timer 1 .Loc 16'FFF0 .16 IRTI ; Real time interrupt .Loc 16'FFFE .16 Deb ;Le vecteur de démarrage .End