;*******************************************************************************
; Title: Keyboardswitch-deluxe
; Author: Anders Runeson, arune@users.sf.net
; Andreas Fritiofson,
; Version:
; Date: 2003/06/xx - 2004/xx/xx
;
; Target: AT90Sxxxx (All AVR Devices)
;
; DESCRIPTION
;
;
; The timing is adapted for 4 MHz xtal
;
; Usage:
;
;
;*******************************************************************************
;todo:
;
;funktion: blinka led d堥n pc bootas
;
;spara saker i eeprom
;
.include "2313def.inc"
;Hardware:
.equ KBD_CK =PB7 ;PD5
.equ KBD_DATA =PB6 ;PD4
.equ PCc_CK =PB4 ;PB5
.equ PCc_DATA =PB5 ;PB4
.equ PCb_CK =PB2 ;PB3
.equ PCb_DATA =PB3 ;PB2
.equ PCa_CK =PB0 ;PB1
.equ PCa_DATA =PB1 ;PB0
.equ MOUSEc_E =PD3
.equ MOUSEb_E =PD4
.equ MOUSEa_E =PD5
;debug
.equ Uart_TxD =PD1 ;o_Data to UART is PD1
.equ Uart_RxD =PD0 ;i_Data from UART is PD0
;.equ LED =PD2
; Status flags
.equ VALID =0 ; There's new valid data in RxByte
.equ ERROR =1 ; There was an error during last reception
.equ BREAK =2 ; Last byte received was a break (F0)
.equ EXTENDED =3 ; Last byte received was "extended" (E0)
.equ KB_CAPS =4 ; Use Caps as function-key, flag indicates if Caps is being pressed
;Define regs used
.def parity_cnt =R4
.def temp2 =R8
.def temp3 =R9
.def blkcnt1 =R10
.def blkcnt2 =R11
.def blkcnt3 =R12
.def ledstatus =R13
.def bootingcomp =R14
.def temp =R17
.def Status =R18
.def bitcnt =R20
.def TxByte =R21 ;kan anv䮤a samma reg ifall det krisar sig (kanske inte, kolla processdata)
.def RxByte =R22
.def LoopPC =R23
.def CurrentPC =R24
.def ConnectedPCs =R25
;for PCa: LoopPC=0b00000001, PCb: LoopPC=0b00000100, PCc: LoopPC=0b00010000, PCd: LoopPC=0b01000000
;same with CurrentPC
;***** Other
;This is what avr responds when pc asks for ID (0xF2)
.equ KBD_ID0 =0xAB
.equ KBD_ID1 =0x83
.equ KBD_ACK =0xFA
.equ KBD_BAT_SUCCESS =0xAA
.equ KBD_ECHO =0xEE
.equ KBD_TMDelay =0b01 ;Typematic repeat delay (0b00=250ms, 0b01=500ms, 0b10=750ms, 0b11=1000ms)
.equ KBD_TMRate =0b00100 ;Typematic repeat rate
;0b00000=30.0cps -> 0b11111=2.0cps
;30.0, 26.7, 24.0, 21.8, 20.0, 18.5, 17.1, 16.0 , 15.0, 13.3, 12.0, 10.9, 10.0, 9.2, 8.6, 8.0, 7.5, 6.7, 6.0, 5.5, 5.0, 4.6, 4.3, 4.0, 3.7, 3.3, 3.0, 2.7, 2.5, 2.3, 2.1, 2.0
.equ MOUSEPORTMASK =0b00111000 ;which ports on PD have a mouse_enable connected
;TODO; flytta om dessa, klart?
.equ NUMLOCKLED =0x02
.equ SCROLLOCKLED =0x01
.equ CAPSLOCKLED =0x04
;.equ CONNECTED_PCs =0b00001100 ;1 PCs 0b00000011, 2 PCs 0b00001111, 3 PCs 0b00111111, 4 PCs 0b11111111
;#############################################################
;# RESET #
;#############################################################
.ORG 0x00
rjmp RESET ;Reset Handler
;.ORG OVF1addr
; rjmp OVFL_TIM1 ;Timer1 Overflow handler
RESET:
cli ;Disable interrupts
;#############################################################
;# INIT #
;#############################################################
;INIT STACKPOINTER
ldi temp,low(RAMEND)
out SPL,temp
;INIT PORT D
;set inputs/outputs (1 = output)
ldi temp,(1<<MOUSEa_E)|(1<<MOUSEb_E)|(1<<MOUSEc_E) ;|(1<<LED)
out DDRD,temp
;set PORT-status (1 = pullup for inputs)
ldi temp,(0<<MOUSEa_E)|(0<<MOUSEb_E)|(0<<MOUSEc_E) ;|(1<<LED)
out PORTD,temp
;INIT PORT B
;set inputs/outputs (1 = output)
ldi temp,(0<<KBD_CK)|(0<<KBD_DATA)|(0<<PCa_CK)|(0<<PCa_DATA)|(0<<PCb_CK)|(0<<PCb_DATA)|(0<<PCc_CK)|(0<<PCc_DATA) ;|(0<<PCd_CK)|(0<<PCd_DATA)
out DDRB,temp
;set PORT-status (1 = pullup for inputs)
ldi temp,(0<<KBD_CK)|(0<<KBD_DATA)|(0<<PCa_CK)|(0<<PCa_DATA)|(0<<PCb_CK)|(0<<PCb_DATA)|(0<<PCc_CK)|(0<<PCc_DATA) ;|(0<<PCd_CK)|(0<<PCd_DATA)
out PORTB, temp
;INIT UART
; ldi temp,(1<<TXEN) ;|(1<<RXEN) ;0b00011000
; out UCR,temp
; ldi temp,12 ;25=9600, 12=19200,
; out UBRR,temp
;INIT TIMER1 - 16bit
;start timer1
;timer1 is used as watchdog timeout (not exacly, but almost), so that the program doesnt get stuck
;in routines checking ports (loops)
ldi temp,0b00000001 ;no prescaler, running timer on CK
out TCCR1B,temp
;INIT EXT-INTERRUPT
;INIT KEYBOARD
;almost all commands from the pc is ignored (see process_to_keyb)
;below there are some commands sent to keyb manually, like reset and set typematic rate/delay
;Send keyboard reset
ldi TxByte,0xFF
rcall avr_to_keyb
rcall delay100us
rcall Wait_keyb_byte ;catch ack
rcall delay100us
rcall Wait_keyb_byte ;catch BAT_SUCCESS
rcall delay100us
;send command typematic rate/delay to keyboard
ldi TxByte,0xF3
rcall avr_to_keyb
rcall delay100us
rcall Wait_keyb_byte ;catch ack
rcall delay100us
;send argument to command "typematic rate/delay"
ldi TxByte,(KBD_TMDelay<<5)|(KBD_TMRate<<0)
rcall avr_to_keyb
rcall delay100us
rcall Wait_keyb_byte ;catch ack
rcall delay100us
ldi LoopPC,0b00000001
ldi CurrentPC,0b00000001 ;IMPORTANT INSTRUCTION!
clr ConnectedPCs ;let routines check which pcs are "on"
sbi PORTD,MOUSEa_E ;choose a mouse at reset
clr Status
sei
;#############################################################
;# MAIN #
;#############################################################
;***** Program Execution Starts Here **************************************
;debug
;ldi TxByte, 0x1C
;rcall avr_to_pc
;ldi TxByte,0xEE
;rcall avr_to_keyb
Start:
;debug
;sbi PORTD,LED
;reset timer
clr temp
out TCNT1h,temp
out TCNT1l,temp
;debug (uart-rx is not connected!)
;sbic USR,RXC
;rcall uart_reciev
;check if pc specified by LoopPC is active/on/ok
rcall check_connected_pc
lsl LoopPC
rol LoopPC
cpi LoopPC,0b01000000
brne skipKBports
ldi LoopPC,0b00000001
;brne skip_carry_rol
;rol LoopPC
;skip_carry_rol:
skipKBports:
mov temp,LoopPC
and temp,ConnectedPCs ;check if pc is "connected"
breq Start ;if not connected goto start and check if connected, then goto next computer
;debug
;mov temp,LoopPC
;rcall uartsend
check_ports:
rcall pc_to_avr ; Read from pc if it tries to send
sbrc Status, VALID ; If new data is available, process it
rcall process_to_keyb ; and send it to the keyboard if neccessary
rcall keyb_to_avr ; Read from keyboard if it tries to send
sbrc Status, VALID ; If new data is available, process it and
rcall process_to_pc ; send it to the current pc if neccessary
rjmp Start
check_connected_pc:
;check all pcs clock- and data-line, if they are idle then set bit in ConnectedPCs
;f?ara hur denna rutinen fungerar
; push LoopPC
; ldi LoopPC,0b00000001
; ccp_do:
rcall read_pc_data ;if not idle, jump/quit routine
breq ccp_skip_setb
rcall read_pc_ck ;if not idle, jump/quit routine
breq ccp_skip_setb
;both lines is idle, this is the key to being considered connected after being disconnected,
;if any of the ports is not idle there can be an error, both line idle => secure to consider connected
;(at least if idle for some ms)
mov temp,ConnectedPCs
and temp,LoopPC ;if connected
brne ccp_skip_setb ;return
;else:
or ConnectedPCs,LoopPC ;consider connected
ccp_skip_setb:
ret
Delay_halfbit:
ldi temp, (36*4-9)/3 ; Delay half a bit or around 36 ?s at 4 MHz and 3 cycles per loop
Delay_halfbit_inner:
dec temp
brne Delay_halfbit_inner
ret
delay100us:
ldi temp,(100*4-9)/3 ; Delay 100 ?s at 4 MHz and 3 cycles per loop
delay100us1:
dec temp
brne delay100us1
ret
delay5us:
ldi temp,(5*4-9)/3 ; Delay 5 ?s at 4 MHz and 3 cycles per loop
delay5us1:
dec temp
brne delay5us1
r
评论0