;--------------------------------------------------------------------------------------------- ; CLOCK/TIMING INFORMATION: ;--------------------------------------------------------------------------------------------- ; ; PS/2 bus clock low time = 40 us +/- 25% (30 us - 50 us) ; PS/2 bus clock high time = 40 us +/- 25% (30 us - 50 us) ; RC osc @ 20pF/5k = 4.61 MHz +/- 25% (3.50 MHz - 5.76 MHz) ; 1 instruction cycle @ 4.61 MHz (RC) = 0.87 us +/- 25% (0.65 us - 1.09 us) ; Optimum PS/2 bus clock low time @4.61MHz = 45.97 instruction cycles ; Actual PS/2 bus clock low time = 46 instruction cycles ; Actual PS/2 bus clock low time @4.61MHz (RC) = 40.0us +/- 25% (30us-50us) ; Actual PS/2 bus clock frequency @461MHz (RC) = 12.5 kHz +/- 25% (10.0kHz-16.7kHz) ;--------------------------------------------------------------------------------------------- ; HEADER: ;--------------------------------------------------------------------------------------------- TITLE "PS/2 Device Routines" SUBTITLE "By Adam Chapweske" LIST P=16F84 INCLUDE "p16f84.inc" RADIX DEC ERRORLEVEL -224, 1 __CONFIG _CP_OFF & _WDT_OFF & _RC_OSC ;--------------------------------------------------------------------------------------------- ; DEFINES: ;--------------------------------------------------------------------------------------------- #DEFINE DATA PORTB, 7 #DEFINE CLOCK PORTB, 6 ;--------------------------------------------------------------------------------------------- ; RAM ALLOCATION: ;--------------------------------------------------------------------------------------------- cblock TEMP0 RECEIVE PARITY COUNTER endc ;--------------------------------------------------------------------------------------------- ;Required Routines & Macros: ;--------------------------------------------------------------------------------------------- ; MACROS: ;--------------------------------------------------------------------------------------------- Delay macro Time ;Delay "Cycles" instruction cycles if (Time==1) nop exitm endif if (Time==2) goto $ + 1 exitm endif if (Time==3) nop goto $ + 1 exitm endif if (Time==4) goto $ + 1 goto $ + 1 exitm endif if (Time==5) goto $ + 1 goto $ + 1 nop exitm endif if (Time==6) goto $ + 1 goto $ + 1 goto $ + 1 exitm endif if (Time==7) goto $ + 1 goto $ + 1 goto $ + 1 nop exitm endif if (Time%4==0) movlw (Time-4)/4 call Delay_Routine exitm endif if (Time%4==1) movlw (Time-5)/4 call Delay_Routine nop exitm endif if (Time%4==2) movlw (Time-6)/4 call Delay_Routine goto $ + 1 exitm endif if (Time%4==3) movlw (Time-7)/4 call Delay_Routine goto $ + 1 nop exitm endif endm ;--------------------------------------------------------------------------------------------- ; DELAY: ;--------------------------------------------------------------------------------------------- ;Delays 4w+4 cycles (including call,return, and movlw) (0=256) Delay_Routine addlw -1 ;Precise delays used in I/O btfss STATUS, Z goto Delay_Routine return ;-------------------------------------------------------------------------------- ;ByteOut: ;Sends a byte in w to the host. Returns 0xFE if inhibited during transmission. Returns 0xFF if host interrupts to send its own data. Returns 0x00 if byte sent successfully. ;--------------------------------------------------------------------------------------------- ; OUTPUT ONE BYTE: - TIMING IS CRITICAL!!! ;--------------------------------------------------------------------------------------------- ByteOut movwf TEMP0 InhibitLoop btfss CLOCK ;Test for inhibit (si la ligne CLOCK est à 1 on sort de la boucle InhibitLoop) goto InhibitLoop Delay 50 ;attente btfss CLOCK ;nouveau test goto InhibitLoop ;la ligne est à zéro btfss DATA ;Check for request-to-send (test PORTB,7) retlw 0xFF ;la sous routine retourne FF (le PC(maître) a mis la ligne à 0 ; pour envoyer une donnée) clrf PARITY ;la ligne est à l'état haut et accepte l'envoi, le bit de parité est mis à zéro) movlw 0x08 ;Nombre de bits à envoyer en w movwf COUNTER ;mis en mémoire movlw 0x00 ;0 dans w call BitOut ;Start bit (0) envoi du start bit btfss CLOCK ;Test for inhibit on teste si la ligne est toujours disponible goto ByteOutEnd ;si la ligne n'est pas libre on va à la sous routine de fin de byte Delay 4 ;attente ;sous routine d'émission d'un octet ByteOutLoop movf TEMP0, w ;TEMP0 en w xorwf PARITY, f ;OU exclusif (0 si 1 et 1) entre w et f, résultat en f ;la première fois PARITY est à O et XOR avec w ==> w en f ;puis TEMPO est décalé à Dte. ;le XOR avec w correspond à une addition avec report à chaque boucle dont le résultat ;est stocké dans PARITY. La fonction BitOut envoie le bit 0 (pair ou impair) ;de cet octet call BitOut ;sortie d'un bit (paramètre en w) btfss CLOCK ;Test for inhibit goto ByteOutEnd ;si la ligne n'est pas libre on va à la sous routine de fin de byte rrf TEMP0, f ;rotation à droite de TEMPO à travers la carry decfsz COUNTER, f ;decrémentation du compteur et saut de l'instruction suivante si zéro goto ByteOutLoop ;on n'a pas encore envoyé tout l'octet Delay 2 ;l'octet a été envoyé comf PARITY, w ;complémentation du bit de parité, résultat dans w call BitOut ;Parity bit: envoi du bit de parité inversé btfss CLOCK ;Test for inhibit goto ByteOutEnd ;si la ligne n'est pas libre on va à la sous routine de fin de byte Delay 5 ;la ligne est libre, attente movlw 0xFF ;FF en w call BitOut ;envoi Stop bit (1) Delay 48 retlw 0x00 ;Returns 0x00 if byte sent successfully ByteOutEnd bsf STATUS, RP0 ;sélectionne banque 1 bsf DATA ;met PORTB, 7 à 1 bsf CLOCK ;met PORTB, 6 à 1 bcf STATUS, RP0 ;sélectionne banque 0 retlw 0xFE ;Returns 0xFE if inhibited during transmission BitOut bsf STATUS, RP0 ;sélectionne banque 1 andlw 0x01 ;and 01 et w affecte Z btfss STATUS, Z ;teste Z du status, saute l'instruction suivante si Z=1 bsf DATA ;met PORTB, 7 à 1 btfsc STATUS, Z ;teste Z du status, saute l'instruction suivante si Z=0 bcf DATA ;met PORTB, 7 à 0 Delay 21 ;attente CLOCK à l'état haut pour respecter le timing d'envoi bcf CLOCK ;met CLOCK à 0 (signal d'horloge état bas) Delay 45 ;attente CLOCK à l'état bas bsf CLOCK ;met CLOCK à 1 bcf STATUS, RP0 ;sélectionne banque 0 Delay 5 return ;-------------------------------------------------------------------------------------------- ;ByteIn: ;Reads a byte from the host. Result in "RECEIVE" register. Returns 0xFE in w if host aborts transmission. ;Returns 0xFF in w if framing/parity error detected. Returns 0x00 in w if byte received successfully. ;--------------------------------------------------------------------------------------------- ; READ ONE BYTE: - TIMING IS CRITICAL!!! ;--------------------------------------------------------------------------------------------- ByteIn btfss CLOCK ;Wait for start bit goto ByteIn btfsc DATA ;Teste l'état de la ligne et saute l'instruction suivante si 0 (start bit) goto ByteIn movlw 0x08 ;intialisation du compteur et du bit de parité movwf COUNTER clrf PARITY Delay 28 ByteInLoop call BitIn ;Data bits (au retour le bit correspondant est en w (00 ou 80) btfss CLOCK ;Test for inhibit saute l'instruction suivante si CLOCK à 1 retlw 0xFE ;transmission avortée bcf STATUS, C ;Carry à 0 dans status rrf RECEIVE, f ;Rotation à Dte avec Carry de l'octet RECEIVE en mémoire ;le LSB (Bit 0)est reçu en premier iorwf RECEIVE, f ;OU inclusif entre w et RECEIVE résultat en f ;vient ajouter 1 bit de poids supérieur à chaque fois xorwf PARITY,f ;addition avec report dans PARITY decfsz COUNTER, f ;décrémentation du compteur et sortie de la boucle quand Z=0 goto ByteInLoop Delay 1 call BitIn ;Parity bit (réception du bit de parité) btfss CLOCK ;Test for inhibit retlw 0xFE ;transmission avortée xorwf PARITY, f ;OU exclusif avec PARITY, résultat en f Delay 5 ;Acquisition du Stop bit ByteInLoop1 Delay 1 call BitIn ;Stop bit (DATA=1 ==> w=80) btfss CLOCK ;Test for inhibit retlw 0xFE ;transmission avortée xorlw 0x00 ;OU exclusif w avec 00 btfsc STATUS, Z ;si résultat=0 sauter l'instruction suivante clrf PARITY ;PARITY=0 (le stop bit a été détecté, on réinitialise PARITE pour la réception suivante) btfsc STATUS, Z ;Stop bit=1? oui on sort de la boucle goto ByteInLoop1 ;No--keep clocking. ;Acknowledge (accusé de réception des données) bsf STATUS, RP0 ;sélection banque 1 bcf DATA ;DATA = 0 Delay 11 bcf CLOCK ;CLOCK = 0 Delay 45 bsf CLOCK ;CLOCK = 1 Delay 7 bsf DATA ;DATA = 1 bcf STATUS, RP0 ;sélection banque 0 btfss PARITY, 7 ;Parité correcte? (test sur le bit 7) saute l'instruction suivante si oui retlw 0xFF ;No--return error Delay 45 retlw 0x00 ;Returns 0x00 in w if byte received successfully BitIn Delay 8 bsf STATUS, RP0 ;sélectionne banque 1 bcf CLOCK ;met la CLOCK à 0 Delay 45 bsf CLOCK ;met la CLOCK à 1 bcf STATUS, RP0 ;sélectionne banque 0 Delay 21 btfsc DATA ;teste la ligne DATA saute si 0 retlw 0x80 ;w=80h si DATA=1 retlw 0x00 ;w=00h si DATA=0 end