Communication with a PS/2 mouse
using a PIC 16F84
Introduction
As explained in the article Host - PS/2 mouse hardware communication on this site, to test the protocol needed to communicate with a PS/2 mouse I have interfaced it with a properly programmed PIC 16F84.
Pay attention: PS/2 devices are different from serial mice, concerning both communication protocol and electrical levels; in PS/2 mice levels used for supply and data exchange are 0 and +5V, in serial mice we instead find the RS-232 levels, +12V and -12V. This article is concerning a PS/2 mouse. The PIC too must receive a +5V supply. In particular, common (or ground) pins of PIC and PS/2 mouse must be connected together; the same for +5V pins.
To connect the mouse and the microcontroller together I suggest a flying PS/2 plug, to which you can connect the four needed wires. Such wires can then be carried to a prototype board and connected on it to the wires coming from the proper PIC's pins. To operate the PIC I have used the version previous to the one described in the article PIC 16F84 F.F. Evaluation Board on this site. For connections refer to the article about Host - PS/2 mouse hardware communication, to the PS/2 connector pin-out and to the first lines of the assembler list below. If in this way the mouse shouldn't show any sign of life, connect two pull-up resistors between data and clock and +5V supply (that, I repeat, must be the same for the microcontroller and the mouse). Proper values are around 3-10 KOhm.
Take care to connections, to avoid unpleasant damages to devices! Instead of damaging a PIC or a mouse, if you are not really sure of acting correctly you can write me.
Acknowledgement and disclaimers
The material contained in these pages is the result of preliminary tests, project developement and verify carried on by the undersigned in first person.
I guarantee the absolute originality of the material, though obviously not excluding that on the net it could be possible to find something analogous.
Being this material at free disposal of whoever desires it, it is absolutely forbidden any form of use for commercial purposes. I don't assume, of course, any responsibilty for possible direct or indirect damages to things or persons deriving by the use of the informations contained in this article.
PIC and Microchip are registered trademarks.
The assembler program.
Below you can find the list of the assembler program. As you can see watching it, it is substantially a set of routines I have written to send command to the mouse and to receive its answers. As it is a program I have used to carry on some tests, it is not optimized, neither concerning memory usage, nor concerning other aspects. It also contains some sections I used only to check the correspondence between the real protocol and the one described in some other papers on the net (I recognized an important difference; you can find the correct description of the communication protocol in the article Host - PS/2 mouse hardware communication on this site). To show which section of the program is currently executed and eventual error conditions, I used different kinds of blinking of a LED connected to the PIC (for whom who doesn't know it, a series resistor between the PIC's pin and the LED is needed; proper values are from 330 Ohm to 1 KOhm). Values used for waiting cycles refers to a clock frequency of 4 MHz, that is 1 million instructions per second. Data sent from the mouse about motion and switches status are not used. If you wish, to you now the task to use my routines making them suitable for your applications. Good luck!
;pag.1
; filename: mouseps2.asm
;
;
; receives data in a serial way from a
; PS/2 mouse;
; used lines are two: clock and data.
; As these lines must be open collector,
; RA2 (Clock) and RA3 (Data) are used as
; LOW output when it's to the host to drive
; them, while when they must be HIGH or
; when they have to be driven by the mouse
; they are set as inputs.
; RA0 (Clock) and RA1 (Data) are used
; as inputs to test Clock and Data lines.
; RB0 is used (as output) for giving
; informations about the communication
; status and about reception errors.
PROCESSOR 16F84
RADIX DEC
__CONFIG 3FF1H
; XT
; /PWRO enable
; WDT disable
INCLUDE "P16F84.INC"
TOCS EQU 05H
CIN EQU 0
DIN EQU 1
COUT EQU 2
DOUT EQU 3
STBIT EQU 0
ENDBIT EQU 1
RA0 EQU 0
RA1 EQU 1
RA2 EQU 2
RA3 EQU 3
RA4 EQU 4
RB0 EQU 0
RB1 EQU 1
RB2 EQU 2
RB3 EQU 3
RB4 EQU 4
RB5 EQU 5
RB6 EQU 6
RB7 EQU 7
ORG 0CH
count RES 1
; pag.2
cbit RES 1
cbyte RES 1
delay1 RES 1
delay2 RES 1
delay3 RES 1
byteo RES 1
byteio RES 1
bytein RES 1
parbit RES 1
byte1 RES 1
byte2 RES 1
byte3 RES 1
byte4 RES 1
serv RES 1
hexd0 RES 1
hexd1 RES 1
hexd2 RES 1
decd0 RES 1
decd1 RES 1
decd2 RES 1
currd RES 1
number RES 1
workdi RES 1
servst RES 1
servw RES 1
servir RES 1
; ATTENZIONE: mantenere sempre a 0 il bit
; RP0 di STATUS ( selezione banco 0)
; per leggere il TMR0, settare tale bit solo ove
; serva e poi riazzerarlo
ORG 00H
goto start
ORG 50H
start
bsf STATUS,RP0
; RB1-7: INPUT
; RB0: INPUT
movlw 11111111B
movwf TRISB
; RA4 :INPUT (non utilizzato)
; RA3, RA2 : INPUT
; RA1, RA0 : INPUT
movlw 11111111B
movwf TRISA
bcf STATUS,RP0
; pag.3
; disattiva Clock e Data
movlw 11111111B
movwf PORTA
movlw 11111111B
movwf PORTB
bsf STATUS,RP0
; assegna al tmr0 la fosc/4
bcf OPTION_REG,TOCS
; assegna il prescaler al tmr0 con valore 256
; (111)
; bsf OPTION_REG,PSA
; bsf OPTION_REG,PS2
; bsf OPTION_REG,PS1
; bsf OPTION_REG,PS0
bcf STATUS,RP0
; movlw 00H
; movwf hexd2
; movwf hexd1
; movwf hexd0
; movwf decd2
; movwf decd1
; movwf decd0
; movwf number
; movwf servst
; movwf servw
; movwf serv
; movlw 00H
; movwf currd
; movwf workdi
; movlw 00H
; movwf count
movlw 00H
movwf TMR0
; attende 1 s
call del1s
; emette tre volte il segnale di comando inviato
; per indicare l'inizio operazioni
call cmdsnt
call cmdsnt
call cmdsnt
; invia il comando di reset (FFH)
movlw 0FFH
movwf byteo
movwf byteio
call cmdts
call sendby
call cmdsnt
; pag.4
; attende 1 s
call del1s
; emette il comando di enable (F4H)
movlw 0F4H
movwf byteo
movwf byteio
call cmdts
call sendby
call cmdsnt
; attende 1 s
call del1s
; emette il comando di impostazioni di default
; (F6H)
movlw 0F6H
movwf byteo
movwf byteio
call cmdts
call sendby
call cmdsnt
call del1s
; richiede la trasmissione dati (EBH)
movlw 0EBH
movwf byteo
movwf byteio
call cmdts
call sendby
call cmdsnt
call del1s
; richiede la trasmissione dati (EBH)
movlw 0EBH
movwf byteo
movwf byteio
call cmdts
call sendby
call cmdsnt
call del1s
; set stream mode (EAH)
movlw 0EAH
movwf byteo
movwf byteio
; pag.5
call cmdts
call sendby
call cmdsnt
call del1s
; richiede la trasmissione dati (EBH) dopo
; aver settato lo stream mode
movlw 0EBH
movwf byteo
movwf byteio
call cmdts
call sendby
call cmdsnt
call del1s
; ricezione dati continua (ogni 100 ms)
datain
call del.1s
; richiede la trasmissione dati (EBH)
movlw 0EBH
movwf byteo
movwf byteio
call sendby
call recby
movf byteio,W
xorlw 0FFH
btfsc STATUS,Z
goto datain
movf bytein,W
movwf byte4
call recby
movf byteio,W
xorlw 0FFH
btfsc STATUS,Z
goto datain
movf bytein,W
movwf byte3
call recby
movf byteio,W
xorlw 0FFH
btfsc STATUS,Z
goto datain
movf bytein,W
movwf byte2
call recby
movf byteio,W
; pag.6
xorlw 0FFH
btfsc STATUS,Z
goto datain
movf bytein,W
movwf byte1
bsf STATUS,RP0
bcf TRISB,RB0
bcf STATUS,RP0
bsf PORTB,RB0
call del10m
bsf STATUS,RP0
bsf TRISB,RB0
bcf STATUS,RP0
bcf PORTB,RB0
goto datain
goto fine
recby
; ricezione dati - restituisce il byte ricevuto in
; bytein; se c'e' stato
; un qualsiasi errore restituisce
; byteio=11111111B, altrimenti byteio=0
movlw 00H
movwf bytein
movlw 08H
movwf cbit
waitst
; attende che il clock vada a 0 e inserisce
; come bit numero 0 di byteio
; il bit presente su RA1 (Data)
; attende il bit di start (linea RA1)
movf PORTA,W
btfsc PORTA,RA0
goto waitst
; ad inizio ricezione porta alto il valore del
; piedino RB0
bsf STATUS,RP0
bcf TRISB,0
bcf STATUS,RP0
bsf PORTB,RB0
movwf serv
rrf serv,W
andlw 00000001B
xorlw STBIT
andlw 00000001B
call wcup
; pag.7
; se il bit di start è diverso da STBIT segnala
; errore
btfsc STATUS,Z
goto stbok
call estb
movlw 0FFH
movwf byteio
goto endrec
stbok
movlw 08H
movwf cbit
movlw 00H
movwf byteio
; riceve gli 8 bit
waitb
movf PORTA,W
btfsc PORTA,RA0
goto waitb
movwf serv
rrf serv,W
andlw 00000001B
btfsc STATUS,Z
goto carry0
carry1
bsf STATUS,C
goto storeb
carry0
bcf STATUS,C
storeb
rrf byteio,F
call wcup
decfsz cbit
goto waitb
movf byteio,W
movwf bytein
; riceve il bit di parità
waitpy
movf PORTA,W
btfsc PORTA,RA0
goto waitpy
movwf serv
call wcup
; calcola la parità del byte contenuto in byteio
; e la restituisce in parbit
call pargen
rrf serv,W
andlw 00000001B
xorwf parbit,W
btfss W,0
goto pbok
call eparb
movlw 0FFH
movwf byteio
goto endrec
; pag.8
pbok
nop
; attende il bit di stop
waitsb
movf PORTA,W
btfsc PORTA,RA0
goto waitsb
movwf serv
rrf serv,W
andlw 00000001B
xorlw ENDBIT
andlw 00000001B
call wcup
; se il bit di stop è diverso da ENDBIT segnala
; errore
btfsc STATUS,Z
goto ebok
call eendb
movlw 0FFH
movwf byteio
goto endrec
ebok
bsf STATUS,RP0
bsf TRISB,RB0
bcf STATUS,RP0
bsf PORTB,RB0
; se byteio = FFH significa che c'è stato
; qualche errore; se si arriva qui
; vuol dire che il byte (che va in bytein
; comunque) è stato ricevuto correttamente
movlw 00H
movwf byteio
endrec
return
; non necessario
goto fine
; calcola la parità del byte contenuto in byteio
; e la restituisce in parbit
pargen
movlw 08H
movwf cbit
movlw 00H
pcycle
xorwf byteio,W
bcf STATUS,C
rrf byteio,F
decfsz cbit
goto pcycle
; pag.9
andlw 00000001B
movwf parbit
return
; pone sulla porta PORTA,DOUT il L.S.bit
; dell'accumulatore: se deve imporre 0,
; lo impone su PORTA,DOUT e configura tale
; piedino come uscita;
; se deve imporre 1, lo impone su tale porta
; (ma non serve) e configura tale
; piedino come ingresso
outbit
andlw 1H
btfsc STATUS,Z
goto outz
goto outuno
outz
bcf STATUS,RP0
bcf PORTA,DOUT
bsf STATUS,RP0
bcf TRISA,DOUT
bcf STATUS,RP0
goto endss
outuno
bsf STATUS,RP0
bsf TRISA,DOUT
bcf STATUS,RP0
bsf PORTA,DOUT
endss
return
; attende che il clock (PORTA,CIN) passi da
; basso ad alto
wcup
btfss PORTA,CIN
goto wcup
return
; attende che il clock (PORTA,CIN) passi da
; alto a basso
wcdown
btfsc PORTA,CIN
goto wcdown
return
; attende che la linea dati (PORTA,DIN) passi
; da basso ad alto
wdup
btfss PORTA,DIN
goto wdup
return
; attende che la linea dati (PORTA,DIN) passi
; da alto a basso
wddown
btfsc PORTA,DIN
goto wddown
return
; pag.10
; errore nel ricevere lo start bit (diversità dalla
; costante STBIT)
; alterna 1 e 0 su RB0 per 8 volte, con periodo
; di circa 0.2 sec, in totale circa 1 sec
estb
bsf STATUS,RP0
bcf TRISB,RB0
bcf STATUS,RP0
movlw 08H
movwf count
cycle2
movlw 00H
movwf delay1
movwf delay2
btfss count,0
goto ozero
goto ouno
ozero
bcf PORTB,RB0
goto cycle3
ouno
bsf PORTB,RB0
cycle3
decfsz delay1
goto cycle3
decfsz delay2
goto cycle3
decfsz count
goto cycle2
bcf PORTB,RB0
bsf STATUS,RP0
bsf TRISB,RB0
bcf STATUS,RP0
return
; errore nel ricevere lo start bit (diversità dalla
; costante STBIT)
; alterna 1 e 0 su RB0 per 16 volte, con periodo
; di circa 0.1 sec, in totale circa 1.5 sec
eparb
bsf STATUS,RP0
bcf TRISB,RB0
bcf STATUS,RP0
movlw 10H
movwf count
cycle4
movlw 00H
movwf delay1
movlw 80H
movwf delay2
btfss count,0
goto ozero1
goto ouno1
; pag.11
ozero1
bcf PORTB,RB0
goto cycle5
ouno1
bsf PORTB,RB0
cycle5
decfsz delay1
goto cycle5
decfsz delay2
goto cycle5
decfsz count
goto cycle5
bcf PORTB,RB0
bsf STATUS,RP0
bsf TRISB,RB0
bcf STATUS,RP0
return
; errore nel ricevere lo stop bit (diversità dalla
; costante ENDBIT)
; alterna 1 e 0 su RB0 per 32 volte, con periodo
; di circa 0.05 sec, in totale circa 1.5 sec
eendb
bsf STATUS,RP0
bcf TRISB,RB0
bcf STATUS,RP0
movlw 20H
movwf count
cycle6
movlw 00H
movwf delay1
movlw 40H
movwf delay2
btfss count,0
goto ozero2
goto ouno2
ozero2
bcf PORTB,RB0
goto cycle7
ouno2
bsf PORTB,RB0
cycle7
decfsz delay1
goto cycle7
decfsz delay2
goto cycle7
decfsz count
goto cycle6
bcf PORTB,RB0
bsf STATUS,RP0
bsf TRISB,RB0
bcf STATUS,RP0
return
; pag.12
; comando inviato - alterna 1 e 0 su RB0 per 2
; volte, con periodo di
; circa 0.5 sec, in totale circa 1 sec
cmdsnt
bsf STATUS,RP0
bcf TRISB,RB0
bcf STATUS,RP0
movlw 02H
movwf count
cycle8
movlw 00H
movwf delay1
movlw 00H
movwf delay2
movlw 02H
movwf delay3
btfsc count,0
goto ozero3
goto ouno3
ozero3
bcf PORTB,RB0
goto cycle9
ouno3
bsf PORTB,RB0
cycle9
decfsz delay1
goto cycle9
decfsz delay2
goto cycle9
decfsz delay3
goto cycle9
decfsz count
goto cycle8
bcf PORTB,RB0
bsf STATUS,RP0
bsf TRISB,RB0
bcf STATUS,RP0
return
; riceve in byteo e byteio il byte da inviare
sendby
bcf STATUS,RP0
bsf PORTB,0
bsf STATUS,RP0
bcf TRISB,0
bcf STATUS,RP0
; forza il clock a 0 e attende circa 200 us
; per far questo pone a 0 e configura come
; uscita il piedino PORTA,COUT
bcf STATUS,RP0
bcf PORTA,COUT
; pag.13
bsf STATUS,RP0
bcf TRISA,COUT
bcf STATUS,RP0
; mettere 42H in delay1 (circa 200 us)
movlw 42H
movwf delay1
cycle1
decfsz delay1
goto cycle1
movlw STBIT
call outbit
; rilascia il clock
bsf STATUS,RP0
bsf TRISA,COUT
bcf STATUS,RP0
bsf PORTA,COUT
call wcup
call wcdown
movlw 08H
movwf cbit
detbit
bcf STATUS,C
rrf byteo,F
btfss STATUS,C
goto bitz
goto bituno
bitz
movlw 00H
goto callob
bituno
movlw 01H
callob
call outbit
call wcup
call wcdown
decfsz cbit
goto detbit
call pargen
movf parbit,W
; PROVA INVERSIONE PARITA'
xorlw 00000001B
call outbit
call wcup
call wcdown
; pag.14
movlw ENDBIT
call outbit
call wddown
call wcdown
call wdup
call wcup
return
; routine di attesa di circa 1ms
del1ms
movlw 02H
movwf delay2
movlw 0A0H
movwf delay1
cyc21
decfsz delay1
goto cyc21
decfsz delay2
goto cyc21
return
; routine di attesa di circa 10ms
del10m
movlw 0DH
movwf delay2
movlw 00H
movwf delay1
cyc51
decfsz delay1
goto cyc51
decfsz delay2
goto cyc51
return
; routine di attesa di circa 100ms
del.1s
movlw 0A0H
movwf delay2
movlw 00H
movwf delay1
cyc41
decfsz delay1
goto cyc41
decfsz delay2
goto cyc41
return
; routine di attesa di circa 1s
del1s
; pag.15
movlw 05H
movwf delay3
movlw 00H
movwf delay2
movwf delay1
cyc11
decfsz delay1
goto cyc11
decfsz delay2
goto cyc11
decfsz delay3
goto cyc11
return
; indica che si sta per inviare un comando - mette 1 su RB0 con un
; impulso di circa 0.1 sec e poi 0 per altri 0.1 sec
cmdts
bsf STATUS,RP0
; pag.16
bcf TRISB,RB0
bcf STATUS,RP0
bsf PORTB,RB0
movlw 00H
movwf delay1
movlw 00H
movwf delay2
cyc31
decfsz delay1
goto cyc31
decfsz delay2
goto cyc31
bcf PORTB,RB0
bsf STATUS,RP0
bsf TRISB,RB0
bcf STATUS,RP0
call del.1s
return
fine
using a PIC 16F84
Introduction
As explained in the article Host - PS/2 mouse hardware communication on this site, to test the protocol needed to communicate with a PS/2 mouse I have interfaced it with a properly programmed PIC 16F84.
Pay attention: PS/2 devices are different from serial mice, concerning both communication protocol and electrical levels; in PS/2 mice levels used for supply and data exchange are 0 and +5V, in serial mice we instead find the RS-232 levels, +12V and -12V. This article is concerning a PS/2 mouse. The PIC too must receive a +5V supply. In particular, common (or ground) pins of PIC and PS/2 mouse must be connected together; the same for +5V pins.
To connect the mouse and the microcontroller together I suggest a flying PS/2 plug, to which you can connect the four needed wires. Such wires can then be carried to a prototype board and connected on it to the wires coming from the proper PIC's pins. To operate the PIC I have used the version previous to the one described in the article PIC 16F84 F.F. Evaluation Board on this site. For connections refer to the article about Host - PS/2 mouse hardware communication, to the PS/2 connector pin-out and to the first lines of the assembler list below. If in this way the mouse shouldn't show any sign of life, connect two pull-up resistors between data and clock and +5V supply (that, I repeat, must be the same for the microcontroller and the mouse). Proper values are around 3-10 KOhm.
Take care to connections, to avoid unpleasant damages to devices! Instead of damaging a PIC or a mouse, if you are not really sure of acting correctly you can write me.
Acknowledgement and disclaimers
The material contained in these pages is the result of preliminary tests, project developement and verify carried on by the undersigned in first person.
I guarantee the absolute originality of the material, though obviously not excluding that on the net it could be possible to find something analogous.
Being this material at free disposal of whoever desires it, it is absolutely forbidden any form of use for commercial purposes. I don't assume, of course, any responsibilty for possible direct or indirect damages to things or persons deriving by the use of the informations contained in this article.
PIC and Microchip are registered trademarks.
The assembler program.
Below you can find the list of the assembler program. As you can see watching it, it is substantially a set of routines I have written to send command to the mouse and to receive its answers. As it is a program I have used to carry on some tests, it is not optimized, neither concerning memory usage, nor concerning other aspects. It also contains some sections I used only to check the correspondence between the real protocol and the one described in some other papers on the net (I recognized an important difference; you can find the correct description of the communication protocol in the article Host - PS/2 mouse hardware communication on this site). To show which section of the program is currently executed and eventual error conditions, I used different kinds of blinking of a LED connected to the PIC (for whom who doesn't know it, a series resistor between the PIC's pin and the LED is needed; proper values are from 330 Ohm to 1 KOhm). Values used for waiting cycles refers to a clock frequency of 4 MHz, that is 1 million instructions per second. Data sent from the mouse about motion and switches status are not used. If you wish, to you now the task to use my routines making them suitable for your applications. Good luck!
;pag.1
; filename: mouseps2.asm
;
;
; receives data in a serial way from a
; PS/2 mouse;
; used lines are two: clock and data.
; As these lines must be open collector,
; RA2 (Clock) and RA3 (Data) are used as
; LOW output when it's to the host to drive
; them, while when they must be HIGH or
; when they have to be driven by the mouse
; they are set as inputs.
; RA0 (Clock) and RA1 (Data) are used
; as inputs to test Clock and Data lines.
; RB0 is used (as output) for giving
; informations about the communication
; status and about reception errors.
PROCESSOR 16F84
RADIX DEC
__CONFIG 3FF1H
; XT
; /PWRO enable
; WDT disable
INCLUDE "P16F84.INC"
TOCS EQU 05H
CIN EQU 0
DIN EQU 1
COUT EQU 2
DOUT EQU 3
STBIT EQU 0
ENDBIT EQU 1
RA0 EQU 0
RA1 EQU 1
RA2 EQU 2
RA3 EQU 3
RA4 EQU 4
RB0 EQU 0
RB1 EQU 1
RB2 EQU 2
RB3 EQU 3
RB4 EQU 4
RB5 EQU 5
RB6 EQU 6
RB7 EQU 7
ORG 0CH
count RES 1
; pag.2
cbit RES 1
cbyte RES 1
delay1 RES 1
delay2 RES 1
delay3 RES 1
byteo RES 1
byteio RES 1
bytein RES 1
parbit RES 1
byte1 RES 1
byte2 RES 1
byte3 RES 1
byte4 RES 1
serv RES 1
hexd0 RES 1
hexd1 RES 1
hexd2 RES 1
decd0 RES 1
decd1 RES 1
decd2 RES 1
currd RES 1
number RES 1
workdi RES 1
servst RES 1
servw RES 1
servir RES 1
; ATTENZIONE: mantenere sempre a 0 il bit
; RP0 di STATUS ( selezione banco 0)
; per leggere il TMR0, settare tale bit solo ove
; serva e poi riazzerarlo
ORG 00H
goto start
ORG 50H
start
bsf STATUS,RP0
; RB1-7: INPUT
; RB0: INPUT
movlw 11111111B
movwf TRISB
; RA4 :INPUT (non utilizzato)
; RA3, RA2 : INPUT
; RA1, RA0 : INPUT
movlw 11111111B
movwf TRISA
bcf STATUS,RP0
; pag.3
; disattiva Clock e Data
movlw 11111111B
movwf PORTA
movlw 11111111B
movwf PORTB
bsf STATUS,RP0
; assegna al tmr0 la fosc/4
bcf OPTION_REG,TOCS
; assegna il prescaler al tmr0 con valore 256
; (111)
; bsf OPTION_REG,PSA
; bsf OPTION_REG,PS2
; bsf OPTION_REG,PS1
; bsf OPTION_REG,PS0
bcf STATUS,RP0
; movlw 00H
; movwf hexd2
; movwf hexd1
; movwf hexd0
; movwf decd2
; movwf decd1
; movwf decd0
; movwf number
; movwf servst
; movwf servw
; movwf serv
; movlw 00H
; movwf currd
; movwf workdi
; movlw 00H
; movwf count
movlw 00H
movwf TMR0
; attende 1 s
call del1s
; emette tre volte il segnale di comando inviato
; per indicare l'inizio operazioni
call cmdsnt
call cmdsnt
call cmdsnt
; invia il comando di reset (FFH)
movlw 0FFH
movwf byteo
movwf byteio
call cmdts
call sendby
call cmdsnt
; pag.4
; attende 1 s
call del1s
; emette il comando di enable (F4H)
movlw 0F4H
movwf byteo
movwf byteio
call cmdts
call sendby
call cmdsnt
; attende 1 s
call del1s
; emette il comando di impostazioni di default
; (F6H)
movlw 0F6H
movwf byteo
movwf byteio
call cmdts
call sendby
call cmdsnt
call del1s
; richiede la trasmissione dati (EBH)
movlw 0EBH
movwf byteo
movwf byteio
call cmdts
call sendby
call cmdsnt
call del1s
; richiede la trasmissione dati (EBH)
movlw 0EBH
movwf byteo
movwf byteio
call cmdts
call sendby
call cmdsnt
call del1s
; set stream mode (EAH)
movlw 0EAH
movwf byteo
movwf byteio
; pag.5
call cmdts
call sendby
call cmdsnt
call del1s
; richiede la trasmissione dati (EBH) dopo
; aver settato lo stream mode
movlw 0EBH
movwf byteo
movwf byteio
call cmdts
call sendby
call cmdsnt
call del1s
; ricezione dati continua (ogni 100 ms)
datain
call del.1s
; richiede la trasmissione dati (EBH)
movlw 0EBH
movwf byteo
movwf byteio
call sendby
call recby
movf byteio,W
xorlw 0FFH
btfsc STATUS,Z
goto datain
movf bytein,W
movwf byte4
call recby
movf byteio,W
xorlw 0FFH
btfsc STATUS,Z
goto datain
movf bytein,W
movwf byte3
call recby
movf byteio,W
xorlw 0FFH
btfsc STATUS,Z
goto datain
movf bytein,W
movwf byte2
call recby
movf byteio,W
; pag.6
xorlw 0FFH
btfsc STATUS,Z
goto datain
movf bytein,W
movwf byte1
bsf STATUS,RP0
bcf TRISB,RB0
bcf STATUS,RP0
bsf PORTB,RB0
call del10m
bsf STATUS,RP0
bsf TRISB,RB0
bcf STATUS,RP0
bcf PORTB,RB0
goto datain
goto fine
recby
; ricezione dati - restituisce il byte ricevuto in
; bytein; se c'e' stato
; un qualsiasi errore restituisce
; byteio=11111111B, altrimenti byteio=0
movlw 00H
movwf bytein
movlw 08H
movwf cbit
waitst
; attende che il clock vada a 0 e inserisce
; come bit numero 0 di byteio
; il bit presente su RA1 (Data)
; attende il bit di start (linea RA1)
movf PORTA,W
btfsc PORTA,RA0
goto waitst
; ad inizio ricezione porta alto il valore del
; piedino RB0
bsf STATUS,RP0
bcf TRISB,0
bcf STATUS,RP0
bsf PORTB,RB0
movwf serv
rrf serv,W
andlw 00000001B
xorlw STBIT
andlw 00000001B
call wcup
; pag.7
; se il bit di start è diverso da STBIT segnala
; errore
btfsc STATUS,Z
goto stbok
call estb
movlw 0FFH
movwf byteio
goto endrec
stbok
movlw 08H
movwf cbit
movlw 00H
movwf byteio
; riceve gli 8 bit
waitb
movf PORTA,W
btfsc PORTA,RA0
goto waitb
movwf serv
rrf serv,W
andlw 00000001B
btfsc STATUS,Z
goto carry0
carry1
bsf STATUS,C
goto storeb
carry0
bcf STATUS,C
storeb
rrf byteio,F
call wcup
decfsz cbit
goto waitb
movf byteio,W
movwf bytein
; riceve il bit di parità
waitpy
movf PORTA,W
btfsc PORTA,RA0
goto waitpy
movwf serv
call wcup
; calcola la parità del byte contenuto in byteio
; e la restituisce in parbit
call pargen
rrf serv,W
andlw 00000001B
xorwf parbit,W
btfss W,0
goto pbok
call eparb
movlw 0FFH
movwf byteio
goto endrec
; pag.8
pbok
nop
; attende il bit di stop
waitsb
movf PORTA,W
btfsc PORTA,RA0
goto waitsb
movwf serv
rrf serv,W
andlw 00000001B
xorlw ENDBIT
andlw 00000001B
call wcup
; se il bit di stop è diverso da ENDBIT segnala
; errore
btfsc STATUS,Z
goto ebok
call eendb
movlw 0FFH
movwf byteio
goto endrec
ebok
bsf STATUS,RP0
bsf TRISB,RB0
bcf STATUS,RP0
bsf PORTB,RB0
; se byteio = FFH significa che c'è stato
; qualche errore; se si arriva qui
; vuol dire che il byte (che va in bytein
; comunque) è stato ricevuto correttamente
movlw 00H
movwf byteio
endrec
return
; non necessario
goto fine
; calcola la parità del byte contenuto in byteio
; e la restituisce in parbit
pargen
movlw 08H
movwf cbit
movlw 00H
pcycle
xorwf byteio,W
bcf STATUS,C
rrf byteio,F
decfsz cbit
goto pcycle
; pag.9
andlw 00000001B
movwf parbit
return
; pone sulla porta PORTA,DOUT il L.S.bit
; dell'accumulatore: se deve imporre 0,
; lo impone su PORTA,DOUT e configura tale
; piedino come uscita;
; se deve imporre 1, lo impone su tale porta
; (ma non serve) e configura tale
; piedino come ingresso
outbit
andlw 1H
btfsc STATUS,Z
goto outz
goto outuno
outz
bcf STATUS,RP0
bcf PORTA,DOUT
bsf STATUS,RP0
bcf TRISA,DOUT
bcf STATUS,RP0
goto endss
outuno
bsf STATUS,RP0
bsf TRISA,DOUT
bcf STATUS,RP0
bsf PORTA,DOUT
endss
return
; attende che il clock (PORTA,CIN) passi da
; basso ad alto
wcup
btfss PORTA,CIN
goto wcup
return
; attende che il clock (PORTA,CIN) passi da
; alto a basso
wcdown
btfsc PORTA,CIN
goto wcdown
return
; attende che la linea dati (PORTA,DIN) passi
; da basso ad alto
wdup
btfss PORTA,DIN
goto wdup
return
; attende che la linea dati (PORTA,DIN) passi
; da alto a basso
wddown
btfsc PORTA,DIN
goto wddown
return
; pag.10
; errore nel ricevere lo start bit (diversità dalla
; costante STBIT)
; alterna 1 e 0 su RB0 per 8 volte, con periodo
; di circa 0.2 sec, in totale circa 1 sec
estb
bsf STATUS,RP0
bcf TRISB,RB0
bcf STATUS,RP0
movlw 08H
movwf count
cycle2
movlw 00H
movwf delay1
movwf delay2
btfss count,0
goto ozero
goto ouno
ozero
bcf PORTB,RB0
goto cycle3
ouno
bsf PORTB,RB0
cycle3
decfsz delay1
goto cycle3
decfsz delay2
goto cycle3
decfsz count
goto cycle2
bcf PORTB,RB0
bsf STATUS,RP0
bsf TRISB,RB0
bcf STATUS,RP0
return
; errore nel ricevere lo start bit (diversità dalla
; costante STBIT)
; alterna 1 e 0 su RB0 per 16 volte, con periodo
; di circa 0.1 sec, in totale circa 1.5 sec
eparb
bsf STATUS,RP0
bcf TRISB,RB0
bcf STATUS,RP0
movlw 10H
movwf count
cycle4
movlw 00H
movwf delay1
movlw 80H
movwf delay2
btfss count,0
goto ozero1
goto ouno1
; pag.11
ozero1
bcf PORTB,RB0
goto cycle5
ouno1
bsf PORTB,RB0
cycle5
decfsz delay1
goto cycle5
decfsz delay2
goto cycle5
decfsz count
goto cycle5
bcf PORTB,RB0
bsf STATUS,RP0
bsf TRISB,RB0
bcf STATUS,RP0
return
; errore nel ricevere lo stop bit (diversità dalla
; costante ENDBIT)
; alterna 1 e 0 su RB0 per 32 volte, con periodo
; di circa 0.05 sec, in totale circa 1.5 sec
eendb
bsf STATUS,RP0
bcf TRISB,RB0
bcf STATUS,RP0
movlw 20H
movwf count
cycle6
movlw 00H
movwf delay1
movlw 40H
movwf delay2
btfss count,0
goto ozero2
goto ouno2
ozero2
bcf PORTB,RB0
goto cycle7
ouno2
bsf PORTB,RB0
cycle7
decfsz delay1
goto cycle7
decfsz delay2
goto cycle7
decfsz count
goto cycle6
bcf PORTB,RB0
bsf STATUS,RP0
bsf TRISB,RB0
bcf STATUS,RP0
return
; pag.12
; comando inviato - alterna 1 e 0 su RB0 per 2
; volte, con periodo di
; circa 0.5 sec, in totale circa 1 sec
cmdsnt
bsf STATUS,RP0
bcf TRISB,RB0
bcf STATUS,RP0
movlw 02H
movwf count
cycle8
movlw 00H
movwf delay1
movlw 00H
movwf delay2
movlw 02H
movwf delay3
btfsc count,0
goto ozero3
goto ouno3
ozero3
bcf PORTB,RB0
goto cycle9
ouno3
bsf PORTB,RB0
cycle9
decfsz delay1
goto cycle9
decfsz delay2
goto cycle9
decfsz delay3
goto cycle9
decfsz count
goto cycle8
bcf PORTB,RB0
bsf STATUS,RP0
bsf TRISB,RB0
bcf STATUS,RP0
return
; riceve in byteo e byteio il byte da inviare
sendby
bcf STATUS,RP0
bsf PORTB,0
bsf STATUS,RP0
bcf TRISB,0
bcf STATUS,RP0
; forza il clock a 0 e attende circa 200 us
; per far questo pone a 0 e configura come
; uscita il piedino PORTA,COUT
bcf STATUS,RP0
bcf PORTA,COUT
; pag.13
bsf STATUS,RP0
bcf TRISA,COUT
bcf STATUS,RP0
; mettere 42H in delay1 (circa 200 us)
movlw 42H
movwf delay1
cycle1
decfsz delay1
goto cycle1
movlw STBIT
call outbit
; rilascia il clock
bsf STATUS,RP0
bsf TRISA,COUT
bcf STATUS,RP0
bsf PORTA,COUT
call wcup
call wcdown
movlw 08H
movwf cbit
detbit
bcf STATUS,C
rrf byteo,F
btfss STATUS,C
goto bitz
goto bituno
bitz
movlw 00H
goto callob
bituno
movlw 01H
callob
call outbit
call wcup
call wcdown
decfsz cbit
goto detbit
call pargen
movf parbit,W
; PROVA INVERSIONE PARITA'
xorlw 00000001B
call outbit
call wcup
call wcdown
; pag.14
movlw ENDBIT
call outbit
call wddown
call wcdown
call wdup
call wcup
return
; routine di attesa di circa 1ms
del1ms
movlw 02H
movwf delay2
movlw 0A0H
movwf delay1
cyc21
decfsz delay1
goto cyc21
decfsz delay2
goto cyc21
return
; routine di attesa di circa 10ms
del10m
movlw 0DH
movwf delay2
movlw 00H
movwf delay1
cyc51
decfsz delay1
goto cyc51
decfsz delay2
goto cyc51
return
; routine di attesa di circa 100ms
del.1s
movlw 0A0H
movwf delay2
movlw 00H
movwf delay1
cyc41
decfsz delay1
goto cyc41
decfsz delay2
goto cyc41
return
; routine di attesa di circa 1s
del1s
; pag.15
movlw 05H
movwf delay3
movlw 00H
movwf delay2
movwf delay1
cyc11
decfsz delay1
goto cyc11
decfsz delay2
goto cyc11
decfsz delay3
goto cyc11
return
; indica che si sta per inviare un comando - mette 1 su RB0 con un
; impulso di circa 0.1 sec e poi 0 per altri 0.1 sec
cmdts
bsf STATUS,RP0
; pag.16
bcf TRISB,RB0
bcf STATUS,RP0
bsf PORTB,RB0
movlw 00H
movwf delay1
movlw 00H
movwf delay2
cyc31
decfsz delay1
goto cyc31
decfsz delay2
goto cyc31
bcf PORTB,RB0
bsf STATUS,RP0
bsf TRISB,RB0
bcf STATUS,RP0
call del.1s
return
fine