Files
SyncHome/trunk/workspace/05_PIC_Projects/16c84-ps2mouse-II_ASM/ps2mouse.asm
2023-03-13 08:36:51 +00:00

791 lines
12 KiB
NASM

;page 1
; filename: mouseps2.asm
;
;
; receives data in a serial way from a
; PS/2 mouse;
; lines used are two: clock and data.
; As these lines should be open collector,
; according to the PS/2 protocol,
; 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 the user
; informations about the communication
; status and about reception errors (as an example, with a LED)
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
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
; WARNING: always keep at 0 the RP0 bit
; of the STATUS register ( selection of bank 0)
; to read the TMR0, set that bit just when needed
; and then set it again to 0
ORG 00H
goto start
ORG 50H
start:
bsf STATUS,RP0
; RB1-7: INPUT
; RB0: INPUT
movlw 11111111B
movwf TRISB
; RA4 :INPUT (unused)
; RA3, RA2 : INPUT
; RA1, RA0 : INPUT
movlw 11111111B
movwf TRISA
bcf STATUS,RP0
; disables Clock and Data
movlw 11111111B
movwf PORTA
movlw 11111111B
movwf PORTB
bsf STATUS,RP0
; assigns fosc/4 to TMR0
bcf OPTION_REG,TOCS
; assigns the prescaler to TMR0 with value 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
; waits 1 s
call del1s
; signals three times "sent command"
; to indicate the start of operations
call cmdsnt
call cmdsnt
call cmdsnt
; sends RESET command (FFH)
movlw 0FFH
movwf byteo
movwf byteio
call cmdts
call sendby
call cmdsnt
; waits 1s
call del1s
; sends ENABLE command (F4H)
movlw 0F4H
movwf byteo
movwf byteio
call cmdts
call sendby
call cmdsnt
; waits 1 s
call del1s
; sends DEFAULT SETTINGS command
; (F6H)
movlw 0F6H
movwf byteo
movwf byteio
call cmdts
call sendby
call cmdsnt
call del1s
; requests data transmission (EBH)
movlw 0EBH
movwf byteo
movwf byteio
call cmdts
call sendby
call cmdsnt
call del1s
; requests data transmission (EBH)
movlw 0EBH
movwf byteo
movwf byteio
call cmdts
call sendby
call cmdsnt
call del1s
; sets stream mode (EAH)
movlw 0EAH
movwf byteo
movwf byteio
call cmdts
call sendby
call cmdsnt
call del1s
; requests data transmission (EBH) after
; stream mode setting
movlw 0EBH
movwf byteo
movwf byteio
call cmdts
call sendby
call cmdsnt
call del1s
; continuous data reception (every 100 ms)
datain
call del.1s
; requests data transmission (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
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:
; data reception - returns the received byte in
; bytein; if an error of any kind
; has occurred, returns
; byteio=11111111B, otherwise byteio=0
movlw 00H
movwf bytein
movlw 08H
movwf cbit
waitst:
; waits for the clock to go to 0 and inserts
; as bit number 0 of byteio
; the bit on RA1 (Data)
; waits start bit (RA1 pin)
movf PORTA,W
btfsc PORTA,RA0
goto waitst
; sets high RB0 pin when
; reception starts
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
; if start bit is different from STBIT signals
; an error
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
; receives parity bit
waitpy:
movf PORTA,W
btfsc PORTA,RA0
goto waitpy
movwf serv
call wcup
; calculates the parity of the byte in byteio
; and returns it 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
pbok:
nop
; waits for the stop bit
waitsb:
movf PORTA,W
btfsc PORTA,RA0
goto waitsb
movwf serv
rrf serv,W
andlw 00000001B
xorlw ENDBIT
andlw 00000001B
call wcup
; if the stop bit is different from ENDBITsignals
; an error
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
; if byteio = FFH it means that an error
; has occurred; if the programs arrives here
; it means that the byte (anyway put in bytein)
; has been correctly received
movlw 00H
movwf byteio
endrec:
return
; not necessary
goto fine
; calculates the parity of the byte in byteio
; and returns it in parbit
pargen:
movlw 08H
movwf cbit
movlw 00H
pcycle:
xorwf byteio,W
bcf STATUS,C
rrf byteio,F
decfsz cbit
goto pcycle
andlw 00000001B
movwf parbit
return
; sends on PORTA,DOUT the L.S.bit
; of the w register: if a 0 has to be set,
; puts it on PORTA,DOUT and sets that
; pin as an output;
; if a 1 has to be set, puts it on porta
; (but it's not need) and sets that pin
; as an input
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
; waits for the clock (PORTA,CIN) to change from
; low to high
wcup:
btfss PORTA,CIN
goto wcup
return
; waits for the clock (PORTA,CIN) to change from
; high to low
wcdown:
btfsc PORTA,CIN
goto wcdown
return
; waits for data (PORTA,DIN) to change
; from low to high
wdup:
btfss PORTA,DIN
goto wdup
return
; waits for data (PORTA,DIN) to change
; from high to low
wddown:
btfsc PORTA,DIN
goto wddown
return
; error in start bit reception (difference from
; STBIT constant)
; sets alternately 1 and 0 on RB0 8 times, with a period
; of about 0.2 sec, about 1 sec in the whole
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
; error in start bit reception (difference from
; STBIT constant)
; sets alternately 1 and 0 on RB0 16 times, with a period
; of about 0.1 sec, about 1.5 sec in the whole
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
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
; error in stop bit reception (difference from
; ENDBIT constant);
; sets alternately 1 and 0 on RB0 32 times, with a period
; of about 0.05 sec, about 1.5 sec in the whole
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
; command sent - sets alternately 1 and 0 on RB0 2 times,
; with a period of
; about 0.5 sec, about 1 sec in the whole
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
; receives in byteo and byteio the byte to send
sendby:
bcf STATUS,RP0
bsf PORTB,0
bsf STATUS,RP0
bcf TRISB,0
bcf STATUS,RP0
; forces clock to 0 and waits about 200 us
; in order to do this, sets to 0 and configures
; the pin PORTA,COUT as an output
bcf STATUS,RP0
bcf PORTA,COUT
bsf STATUS,RP0
bcf TRISA,COUT
bcf STATUS,RP0
; puts 42H in delay1 (about 200 us)
movlw 42H
movwf delay1
cycle1:
decfsz delay1
goto cycle1
movlw STBIT
call outbit
; releases 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
; TESTS PARITY INVERSION
xorlw 00000001B
call outbit
call wcup
call wcdown
movlw ENDBIT
call outbit
call wddown
call wcdown
call wdup
call wcup
return
; delay routine of about 1 ms
del1ms:
movlw 02H
movwf delay2
movlw 0A0H
movwf delay1
cyc21:
decfsz delay1
goto cyc21
decfsz delay2
goto cyc21
return
; delay routine of about 10 ms
del10m:
movlw 0DH
movwf delay2
movlw 00H
movwf delay1
cyc51:
decfsz delay1
goto cyc51
decfsz delay2
goto cyc51
return
; delay routine of about 100 ms
del.1s:
movlw 0A0H
movwf delay2
movlw 00H
movwf delay1
cyc41:
decfsz delay1
goto cyc41
decfsz delay2
goto cyc41
return
; delay routine of about 1 s
del1s:
movlw 05H
movwf delay3
movlw 00H
movwf delay2
movwf delay1
cyc11:
decfsz delay1
goto cyc11
decfsz delay2
goto cyc11
decfsz delay3
goto cyc11
return
; indicates that a command is about to be sent - sets RB0
; to 1 with a pulse of about 0.1 sec and then
; 0 for 0.1 sec
cmdts:
bsf STATUS,RP0
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:
END