|
;***************************************************************************
;
; File Name :"PS2Drv.asm"
; Title :PS/2 target communication protocoll
; Date :2001.10.06.
; Date (Last) :2002.12.15.
; Version :1.10
; Support telephone :+36-70-333-4034, Old: +36-30-9541-658 VFX
; Support fax :
; Support Email :info@vfx.hu
; Target MCU :AT90S8515
;
;***************************************************************************
; D E S C R I P T I O N
;
; - PS/2 style communication from AT keyboard or MARGOR HI-01 to MAGOR CP01-1v2
;
; CLK & DATA = H -> Two way communication
; DATA = L -> PC (MAGOR) sends to Keyb
; CLK = L -> PC (MAGOR) inhibits communiaction
;
;***************************************************************************
; M O D I F I C A T I O N H I S T O R Y
;
;
; rev. date who why
; ---- ---------- --- --------------------------------------------
; 0.01 2001.10.06 VFX Creation
; 1.02 2001.12.27 VFX Modify for MAGOR CP01-1v2
; 1.10 2002.12.15 VFX Fixed Sendig Command to keyboard, time out added
;
;
;**************************************************************************
;* Hardware Abstraction Layer
.EQU PS2_CLKPort = PORTD
.EQU PS2_CLKDIR = DDRD
.EQU PS2_CLKPIN = PIND
.EQU KCLK = 2
.EQU PS2_DATPort = PORTB
.EQU PS2_DATDIR = DDRB
.EQU PS2_DATPIN = PINB
.EQU KDATA = 0
;***************************************************************************
;* Const Def
.equ wait100us = SYSCLK/10000 ;ennyi ciklus 100us
.EQU Kb_ScData_Lenght = 6 ;Received ScanCode buffer
;--------------------------------
;Define commands to the keyboard.
;
.equ SET_KEYBOARD_INDICATORS = 0xED
.equ KEYBOARD_ECHO = 0xEE
.equ SELECT_SCAN_CODE_SET = 0xF0
.equ READ_KEYBOARD_ID = 0xF2
.equ SET_KEYBOARD_TYPEMATIC = 0xF3
.equ KBD_ENABLE = 0xF4
.equ KBD_DISABLE = 0xF5
.equ SET_ALL_TYPEMATIC_MAKE_BREAK = 0xFA
.equ KEYBOARD_RESET = 0xFF
;---------------------------------
; Define the keyboard responses.
;
.equ ACKNOWLEDGE = 0xFA
.equ RESEND = 0xFE
.equ KEYBOARD_COMPLETE_SUCCESS = 0xAA ;BAT complete
.equ KEYBOARD_COMPLETE_FAILURE = 0xFC
.equ KEYBOARD_BREAK_CODE = 0xF0
.equ KEYBOARD_DEBUG_HOTKEY_ENH = 0x37 ;SysReq scan code for Enhanced Keyboard
.equ KEYBOARD_DEBUG_HOTKEY_AT = 0x54 ;SysReq scan code for 84-key Keyboard
.equ ST_Success = 0x80 ;a parancs sikeres volt
.equ ST_Unsuccess = 0x81 ;a parancs sikertelen
.equ ST_ResendError = 0x82 ;3-szor probltuk kuldeni a keyboard fele, de nem ment
.equ ST_ACKnotreseived=0x83 ;ACK-t vartunk de nem az jott...
;***************************************************************************
;**** VARIABLES
.DSEG
PtrINT0: .BYTE 2 ;INT0 Keyboard interrupt aktualis cime
;int0 eseten ide ugrik
Kb_BitCounter: .BYTE 1 ;hany bitet olvasott eddig be
ResevedBits: .byte 1 ;received Kb_bits
Kb_Paritas: .byte 1 ;Vett paritas bit
Kb_ScHead: .byte 1 ;Dekodolatlan Scankod buffer Head mutato
Kb_ScTail: .byte 1
Kb_ScData: .byte Kb_ScData_Lenght
kb_SendByte: .byte 1 ;send this data to keyboard
kb_ComStat: .byte 1 ;=0 szabadon megallithato a komunikacio
;=1 komunikacio megallitasa tilos
;=3 kuldes folyamatban
kb_lastAction: .byte 1 ;utolso muvelet mi volt
;=255 normal mukodes
;=0,1,2,3,4,5 command/parameter kuldes volt ACK-ot varunk vissza
kb_CmdBuffer: .byte 3 ;1 CMD + 3 data bytenak van hely
kb_ResendCnt: .byte 1 ;hanyszor probaltuk elkuldeni, ha tobb mint 3 akkor error
kb_Status: .byte 2
jumptabla: .byte 2
kb_SWStatus: .byte 1 ;keyboard status
; [7:6] = 00 Standard PS/2 keyboard
; = 01 MAGOR HI-01 keyboard
; = 1x future
; [5:0] = CAPS,NUM, SCROLL lock & future LEDs
;***************************************************************************
.ESEG
;***************************************************************************
.CSEG
;***************************************************************************
; PS/2 Billentyuzet inicializalasa
;
Init_PS2: CBI PS2_CLKPort,KCLK
CBI PS2_CLKDIR,KCLK ;CLK pin tre-stated external pull-up res!!
CBI PS2_DATPort,KDATA
CBI PS2_DATDIR,KDATA ;DATA pin tre-stated external pull-up res!!
ldi R16,Low(Kb_Rec_Start) ;Most csak adat vetele van!
sts PtrINT0+0,R16
ldi R16,High(Kb_Rec_Start)
sts PtrINT0+1,R16
clr R16
sts Kb_ScHead,R16 ;ScanCode Pointer Head = 0
sts Kb_ScTail,R16
sts kb_ComStat,R16
sts kb_ResendCnt,R16
sts kb_Status,R16
sts kb_SWStatus,R16
ldi R16,255
sts kb_lastAction,R16 ;normal mukodes
ldi R16,11 ;1 start +8 adat +1 par +1 stop
sts Kb_BitCounter,R16
ldi ZL,low(NormalUzem)
ldi ZH,high(NormalUzem)
sts jumptabla+0,ZL
sts jumptabla+1,ZH
in R16,MCUCR
cbr R16,0b00000011 ;mask for 1,0 bits
sbr R16,0b00000010 ;set for falling edge
OUT MCUCR,R16 ;1:0 = Inerrupt Sense Control for INT0
; 00 -> Low Level INT0
; 01 -> Reserved
; 10 -> Falling Edge INT0
; 11 -> Rising Edge INT0
ldi R16,64 ;INT0,1 IRQ flag torlese
out GIFR,R16
in R16,GIMSK
ori R16,64 ;INT0 enabled
OUT GIMSK,R16 ;6. = 1 EXT INT0 ACTIVE
ldi R16,250 ;varunk 2500ms-ig, hogy a power-up reset befejezodjon
sts SWTmr0,R16 ;ha kozben megjon az 0xAA, akkor jo.
WTC0:
lds R16,SWTmr0
tst R16
breq WTCTO ;ha innen ugrik, szinte biztos hogy hiba lesz
sleep
nop
rcall Get_ScanC
brcs WTC0
WTCTO:
rcall kb_CMD_Reset
rcall WaitToComplete
brcs KeybErr
cpi R16,KEYBOARD_COMPLETE_SUCCESS
brne KeybErr
rcall kb_CMD_ReadID
rcall WaitToComplete
brcs KeybErr
ldi R18,64
cpi R16,0xDE
brne nonPS2
cpi R17,0xD0 ;0x83AB nem tudom mi lehet minden billentyu
breq storeType ;0x9EAB -vel ter vissza
;0xDED0 csak MAGOR HI-01 lehet
nonPS2: ldi R18,04 ;Itt csak szabvany billentyu lehet
storeType:
sts kb_SWStatus,R18 ;keyboard tipus eltarolva, majd kesobb kell meg
rcall kb_CMD_ALLMakeBrake
rcall WaitToComplete
brcs KeybErr
cpi R16,ST_Success
brne KeybErr
ldi R17,0 ;30char/s, 250ms rep. time
rcall kb_CMD_SetSpeed
rcall WaitToComplete
brcs KeybErr
cpi R16,ST_Success
brne KeybErr
ldi R17,0
rcall kb_CMD_SetLEDs ;LEDek kikapcsolva
rcall WaitToComplete
brcs KeybErr
cpi R16,ST_Success
brne KeybErr
ldi R16,low(ps2stszov*2)
ldi R17,high(ps2stszov*2)
lds R18,kb_SWStatus
andi R18,0b11000000 ;csak a bill tipusa kell
breq kszoveg
ldi R16,low(magorszov*2)
ldi R17,high(magorszov*2)
rjmp kszoveg
KeybErr:
ldi R16,Low(kbTimeOutErr*2)
ldi R17,High(kbTimeOutErr*2)
kszoveg: rcall SendMSG
ret
;************************************************
;* WaitToComplete
;* kivarja egy billentyuparancs vegrehajtasat vagy time-out
;* R17:R16 ststus kod (redszerint csak az R16 kell)
; c=1 error
WaitToComplete:
ldi R16,40 ;ha 400ms-ig nincs valasz hiba @100Hz rendszermegwszakitas mellett
sts SWTmr0,R16
WTC1: lds R16,SWTmr0
tst R16
breq WTCTimeOut
lds R16,kb_Status+0
cpi R16,0x33
breq WTC1
ldi R17,kb_Status+1
clc
ret
WTCTimeOut: sec
ret
;******************************************************************************
;* INERRUPT: R E C E I V E
;*
;* External generated clock & data - host changes the Data line only when
;* the Clock line is low, and data is latched on the falling edge of the clock pulse
;* Host may abort transmission at time before the 11th clock pulse (acknowledge bit)
;* by holding Clock low for at least 100 microseconds.
;*
;*
EXT_INT0: push ZL
push ZH
in ZL,SREG ; preserve main OS status reg.
push ZL
push R16
push R2
in R2,PS2_DATPIN
bst R2,KDATA ;T-ben a vett bit
lds ZL,PtrINT0+0
lds ZH,PtrINT0+1
icall ;Int0 vegrehajto rutin meghivasa
ldi R16,64 ;INT0 IRQ flag torlese
out GIFR,R16 ;lehet, hogy ez nem kell majd!!!!
pop R2
pop R16
pop ZL
out SREG,ZL ; restore previous status reg
pop ZH
pop ZL
reti
;*****************************************
; Receive 11 keyboard bit
;
Kb_Rec_Start: lds R16,Kb_BitCounter
dec R16
sts Kb_BitCounter,R16
cpi R16,10 ;start bitnel tartunk
breq JaStartbit
cpi R16,1 ;Paritasbit jon?
breq JaParitasJon
cpi R16,0 ;Stopbit jon?
breq JaStopJon
;************************************** ;8 adatbit vetele
;* 8 DATA BIT
Kb_Rec_Dat: lds R16,ResevedBits ;az eddig beolvasott bitek
lsr R16 ;rota 7. -> 0.
bld R16,7 ;az ujbitet a 7. pos-on taroljuk
sts ResevedBits,R16 ;tarolas
clr R2
bld R2,0 ;a paritas generalashoz kell
lds R16,Kb_Paritas
add R16,R2
sts Kb_Paritas,R16 ;uj paritas eltarolva
lds R16,Kb_BitCounter ;ha tobb mint 9 bit jott eddig,
;akor mar nem lehet megallitani
;a vetelt. Be kell fejezni!
cpi R16,4
brsh kb_Rec_end1
ldi R16,1
sts kb_ComStat,R16
kb_Rec_end1: ret
;**************************************
;* START BIT
JaStartbit: clr R16
sts Kb_Paritas,R16 ;Paritas = 0, most meg :)
bld R16,0 ;Received Start bit in pos. 0
tst R16
brne Kb_StartErr
ret
Kb_StartErr:
;ide jon az az eset, ha a start bit = 1 ,azaz hiba van!!!!
;de Vigyazat! Meg interrupt rutinban vagyuk!!!!
ret
;**************************************
; PARITAS BIT
JaParitasJon: clr R16
bld R16,0 ;Paritasbit tarolasa a 0. bitben
lds R2,Kb_Paritas ;R2 vett adat par, R16 vett paritas bit
inc R2 ;paratlan paritas kell!
eor R2,R16 ;R2 = parity xor parity bit
ror R2 ;C-flagben a parity
brcs Kb_RxParErr
ret
Kb_RxParErr: ;ide jon majd a paritas hiba lekezelese
;De figyelem, meg mindig interruptban vagyuk!!!!!!
ret
;************************************
;* STOP BIT
JaStopJon: bld R16,0 ;itt mar R16=0, R16=stop bit
tst R16
breq Kb_StopErr
ldi R16,11 ;1 start +8 adat +1 par +1 stop
sts Kb_BitCounter,R16 ;a kovetkezo adat vetelehez
lds R16,kb_lastAction
cpi R16,255
breq NemParancsvolt
lds R16,ResevedBits
cpi R16,RESEND
brne nemresend
lds R16,kb_ResendCnt
inc R16
sts kb_ResendCnt,R16
cpi R16,4 ;ha mar haromszor probaltuk elkuldeni, de nem ment
;akkor resend error
brne Mehettovabb
ldi R16,255
sts kb_lastAction,R16 ;vissza anormal mukodesre
ldi R16,ST_ResendError
sts kb_Status,R16
ret
Mehettovabb:
rcall NextComdData
ret
nemresend: lds ZL,jumptabla+0
lds ZH,jumptabla+1
ijmp
NemParancsvolt:
rcall Put_ScanC ;Scankod a bufferbe
clr R16
sts kb_ComStat,R16 ;Stop tilalom feloldva!
ret
Kb_StopErr: ;ide jon majd a hibas stop bit lekezelese
;Meg mindig INTERRUPTBAN vagyunk!!!!
clr R16
sts kb_ComStat,R16 ;Stop tilalom feloldva!
ret
;************************************************
;* The Put_ScanC FIFO manager *
;* in: - *
;* out c=1 hiba *
;************************************************
Put_ScanC: lds R16,Kb_ScHead
ldi ZL,Kb_ScData_Lenght
lds R2,Kb_ScTail
sub R2,R16
breq PSC4 ;T=H, akkor Kb_ScData_Lenght hely van
brcs PSC2
clr ZL
PSC2: add ZL,R2
dec ZL
PSC4: cpi ZL,1 ;ZL = hely a bufferben
brcs PSCExitwError ;ha <1 nincs elg hely! Hiba!
clr R2
ldi ZL,low(Kb_ScData) ;Pointer to the buffer (FIFO)
ldi ZH,high(Kb_ScData)
add ZL,R16
adc ZH,R2 ;add address offset..
lds R2,ResevedBits ;ez elobb vet 8 kb_data bit
st Z,R2 ;eltarolva a scankod bufferben
inc R16
cpi R16,Kb_ScData_Lenght ;Pointer>Len
brcs PSC3
clr R16 ;ha igen Pointer=0, atfordult
PSC3: sts Kb_ScHead,R16
ScanCexit: clc ; Nincs hiba
ret
PSCExitwError: ;ide jon az, ha a scankod bufferben nincs hely!
;de mi van ha nincs hely, es meg mindig megszakitasban vagyunk!!
sec ;Hiba!!
ret
;**************************************
; FIFO Manager folytatasa
; mar nem interruptbol megy!!!!
; Out: c=0, R0 = scankod
;
Get_ScanC: clr R0
lds R18,Kb_ScTail
lds R19,Kb_ScHead
cp R19,R18
breq ScanErrExit ;nincs adat a bufferben
ldi ZL,low(Kb_ScData) ;Pointer to the rxbuffer (FIFO)
ldi ZH,high(Kb_ScData)
add ZL,R18
adc ZH,R0 ;add address offset...
ld R0,Z
inc R18
cpi R18,Kb_ScData_Lenght
brlo ScanCbx
clr R18 ;Circle around to the first buffer pos.
ScanCbx: sts Kb_ScTail,R18
clc ;Valid Char
ret
ScanErrExit: sec ;no char in buff, or error
ret
;***************************************************
;* Send data to keyboard
;* start bit sending
;
Kb_StartSend:
lds R16,Kb_BitCounter
dec R16
sts Kb_BitCounter,R16
cpi R16,2
breq SendParitas
cpi R16,1
breq SendStopbit
cpi R16,0
breq GetAckBit
lds R16,kb_SendByte
lds R2,Kb_Paritas
ror R16
sts kb_SendByte,R16
brcs send1bit
CBI PS2_DATPort,KDATA ;send bit 0
inc R2
rjmp kb_sendbitx
send1bit:
SBI PS2_DATPort,KDATA ;send bit 1
kb_sendbitx: ;uj adatbit a porton
sts Kb_Paritas,R2 ;uj paritas eltarolasa
ret
;**************************************
;* Paritas bit kuldese
SendParitas:
lds R16,Kb_Paritas
ror R16
brcc send1paritas
CBI PS2_DATPort,KDATA ;send bit 0
ret
send1paritas:
SBI PS2_DATPort,KDATA ;paritas bit = 1
ret
;***************************************
;* Stop bit kuldese
;
SendStopbit:
CBI PS2_DATPort,KDATA
CBI PS2_DATDIR,KDATA ;DATA pin tre-stated external pull-up!!
ret
;**************************************
;* Get Ack bit from keyboard
;
GetAckBit:
ldi R16,11 ;1 start +8 adat +1 par +1 stop
sts Kb_BitCounter,R16 ;a kovetkezo adat vetelehez
ldi R16,Low(Kb_Rec_Start) ;Vissza allunk adat vetelre
sts PtrINT0+0,R16
ldi R16,High(Kb_Rec_Start)
sts PtrINT0+1,R16
bld R16,0 ;R16=ack bit
tst R16
brne Kb_SendAckErr
ret
Kb_SendAckErr:
;ide jon az az eset amikor nem kuldott ack-ot
;es amost mit kezdjek vele, kuldjem ujra az egeszet???
ret
;***************************************************
;** Parancskuldes kezdemenyezese a keyboard fele
;** In : R0 data to keyboard
;** Out: c=0 sikeres kuldes meginidtasa
;** c=1 sikertelen kuldes
TrySendCmd:
lds R2,kb_ComStat ;Stop tilalom van-e?
tst R2
breq TrySend
sec
NormalUzem: ret
TrySend:
sts jumptabla+0,ZL
sts jumptabla+1,ZH
sts kb_CmdBuffer+0,R16
sts kb_CmdBuffer+1,R17
sts kb_CmdBuffer+2,R18
ldi R16,0x33
sts kb_Status,R16
clr R16
sts kb_lastAction,R16 ;0. byte kuldese lesz
NewParam:
clr R16
sts kb_ResendCnt,R16
NextComdData:
clr R16
lds R2,kb_lastAction ;a kovetkezo byte kuldese
ldi ZL,low(kb_CmdBuffer)
ldi ZH,high(kb_CmdBuffer)
add ZL,R2
adc ZH,R16
ld R0,Z
sts kb_SendByte,R0
in R16,GIMSK
andi R16,0b10111111
OUT GIMSK,R16 ;6. = 0 EXT INT0 inactive
;hogy ne okozzunk megszakitas
;mikor leallitjuk a CLK vonalat
SBI PS2_CLKDIR,KCLK ;CLK push-pull Low
nop
ldi ZL,low(wait100us/5)
ldi ZH,high(wait100us/5) ;100us idozito konstans
w100us: nop ;[1]
sbiw ZL,1 ;[2]
brne w100us ;[2]
nop ;itt mart eszre kellett vegye
;hogy adni akarunk
ldi R16,Low(Kb_StartSend) ;Most parancs kuldes lesz
sts PtrINT0+0,R16
ldi R16,High(Kb_StartSend)
sts PtrINT0+1,R16
ldi R16,3
sts kb_ComStat,R16 ;Stop tilalom lesz az adas allat...
ldi R16,11 ;1 start +8 adat +1 par +1 stop +1 ack
sts Kb_BitCounter,R16
clr R16
sts Kb_Paritas,R16 ;paritas szamolashoz kell
SBI PS2_DATDIR,KDATA ;DATA pin push-pull low
nop
CBI PS2_CLKDIR,KCLK ;CLK tre-state ismet
ldi R16,64 ;INT0 IRQ flag torlese
out GIFR,R16
in R16,GIMSK
ori R16,64
OUT GIMSK,R16 ;6. = 1 EXT INT0 ujra aktive
clc
ret
;jump tablak
;**********************
;* Reset keyboard
;* In: R17,R18,R19 parameter ahol kell
;* Out: status
;
kb_CMD_Reset:
ldi R16,KEYBOARD_RESET
kb_CMD_single: ldi ZL,low(Egyvalasz)
ldi ZH,high(Egyvalasz)
rjmp TrySendCmd
kb_CMD_ALLMakeBrake:
ldi R16,SET_ALL_TYPEMATIC_MAKE_BREAK
ldi ZL,low(CsakACKkell)
ldi ZH,high(CsakACKkell)
rjmp TrySendCmd
kb_CMD_Echo:
ldi R16,KEYBOARD_ECHO
ldi ZL,low(StoreResult)
ldi ZH,high(StoreResult)
rjmp TrySendCmd
kb_CMD_SetLEDs:
andi R17,0b00111111 ;csak az also 6 bit kell -> 6 LEDek
lds R16,kb_SWStatus
andi R16,0b11000000
or R16,R17
sts kb_SWStatus,R16
ldi R16,SET_KEYBOARD_INDICATORS
param1: ldi ZL,low(EgyParameter)
ldi ZH,high(EgyParameter)
rjmp TrySendCmd
kb_CMD_SetSpeed:
ldi R16,SET_KEYBOARD_TYPEMATIC
rjmp param1
kb_CMD_ReadID:
ldi R16,READ_KEYBOARD_ID
ldi ZL,low(ketparamjon)
ldi ZH,high(ketparamjon)
rjmp TrySendCmd
;*************************************************************
;* subrutinok a keyboard parancsok vegrehajtasahoz
;
CsakACKkell:
cpi R16,ACKNOWLEDGE
ldi R16,ST_Success
breq StoreResult
ldi R16,ST_Unsuccess
rjmp StoreResult
Egyvalasz: cpi R16,ACKNOWLEDGE
breq nyugtamegjott
ldi R16,ST_ACKnotreseived
StoreResult:
ldi ZL,low(NormalUzem)
ldi ZH,high(NormalUzem)
sts jumptabla+0,ZL
sts jumptabla+1,ZH
Alaphelyzebe: sts kb_Status,R16
ldi R16,255
sts kb_lastAction,R16 ;vissza anormal mukodesre
clr R16
sts kb_ComStat,R16 ;Stop tilalom feloldva!
ret
nyugtamegjott:
ldi ZL,low(StoreResult)
ldi ZH,high(StoreResult)
sts jumptabla+0,ZL
sts jumptabla+1,ZH
ret
EgyParameter:
cpi R16,ACKNOWLEDGE
breq Elsonyugtaok
ldi R16,ST_ACKnotreseived
rjmp StoreResult
Elsonyugtaok:
lds R16,kb_lastAction ;a kovetkezo byte kuldese
inc R16
sts kb_lastAction,R16
ldi ZL,low(CsakACKkell)
ldi ZH,high(CsakACKkell)
sts jumptabla+0,ZL
sts jumptabla+1,ZH
rjmp NewParam
ketparamjon:
sts kb_Status+1,R16
rjmp nyugtamegjott
|
|