;*************************************************************************** ; ; 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