4. 智能键盘 (ikbd) 协议

4.1. 简介

Atari Corp. 智能键盘 (ikbd) 是一种通用的键盘控制器,它足够灵活,无需修改即可用于各种产品。键盘及其微控制器为鼠标和开关式操纵杆提供了方便的连接点。 ikbd 处理器还维护一个分辨率为 1 秒的实时时钟。 ikbd 的设计非常通用,可以与各种新的计算机产品一起使用。可以容纳许多按键开关、鼠标分辨率等方面的产品差异。 ikbd 通过高速双向串行接口与主处理器通信。它可以以多种模式运行,以方便键盘、操纵杆或鼠标的不同应用。通过仔细设计默认模式,可以在仅有单向通信媒介的应用程序中有限地使用控制器。

4.2. 键盘

键盘始终返回按键按下/释放扫描码。 ikbd 为每次按键和释放生成键盘扫描码。按键扫描码(按键闭合)从 1 开始,并在附录 A 中定义。例如,即使特定键盘上该位置不存在按键开关,扫描码表中的 ISO 按键位置也应该存在。每个按键的释放码通过将 0x80 与按下码进行 OR 运算获得。

特殊代码 0xF6 到 0xFF 保留用于以下用途

代码

命令

0xF6

状态报告

0xF7

绝对鼠标位置记录

0xF8-0xFB

相对鼠标位置记录(最低有效位由鼠标按键状态决定)

0xFC

实时时钟

0xFD

操纵杆报告(两个操纵杆)

0xFE

操纵杆 0 事件

0xFF

操纵杆 1 事件

在此模式下,两个 Shift 键返回不同的扫描码。 ENTER 键和 RETurn 键也是不同的。

4.3. 鼠标

鼠标端口应该能够支持分辨率约为每英寸行程 200 个计数(相位变化或“点击”)的鼠标。应该以允许在高达每秒 10 英寸的速度下进行精确跟踪的速率扫描鼠标。 ikbd 可以以三种截然不同的方式报告鼠标移动。它可以报告相对运动、ikbd 内维护的坐标系中的绝对运动,或者通过将鼠标移动转换为键盘光标控制键等效项。鼠标按键可以被视为鼠标的一部分或附加的键盘按键。

4.3.1. 相对位置报告

在相对位置模式下,当鼠标事件发生时,ikbd 将返回相对鼠标位置记录。鼠标事件包括按下或释放鼠标按键,或者任一轴上的运动超过可设置的运动阈值。无论阈值如何,所有分辨率位都将返回给主机。请注意,ikbd 可能会返回明显大于阈值 delta x 或 y 的鼠标相对位置报告。这可能会发生,因为不会生成任何相对鼠标运动事件:(a)当键盘“暂停”时(事件将被存储直到键盘通信恢复)(b)当任何事件正在传输时。

相对鼠标位置记录是一种三字节记录,形式如下(无论键盘模式如何)

%111110xy           ; mouse position record flag
                    ; where y is the right button state
                    ; and x is the left button state
X                   ; delta x as twos complement integer
Y                   ; delta y as twos complement integer

请注意,即使 MOUSE BUTTON ACTION 已将按键设置为像键盘的一部分一样工作,按键状态位的值也应有效。如果报告数据包生成之前累积的运动超过 +127...-128 范围,则运动将分解为多个数据包。 请注意,报告的 delta y 的符号是所选 Y 原点的函数。

4.3.2. 绝对位置报告

ikbd 还可以维护绝对鼠标位置。存在用于重置鼠标位置、设置 X/Y 缩放以及询问当前鼠标位置的命令。

4.3.3. 鼠标光标键模式

ikbd 可以将鼠标移动转换为等效的光标按键。每个轴上每次击键的鼠标点击次数是独立可编程的。 ikbd 在内部将鼠标运动信息维护到可用的最高分辨率,并且仅为每个比例因子的倍数生成一对光标按键事件。鼠标运动会产生光标按键按下代码,紧接着是相应光标按键的释放代码。鼠标按键会生成高于为最大设想的键盘正常分配的扫描码(即 LEFT=0x74 & RIGHT=0x75)。

4.4. 操纵杆

4.4.1. 操纵杆事件报告

在此模式下,每当操纵杆位置改变时(即,每次打开或关闭操纵杆开关或触发器时),ikbd 都会生成一个记录。

操纵杆事件记录是两个字节,形式如下

%1111111x           ; Joystick event marker
                    ; where x is Joystick 0 or 1
%x000yyyy           ; where yyyy is the stick position
                    ; and x is the trigger

4.4.2. 操纵杆查询

通过向 ikbd 发送“查询操纵杆”命令,可以在此模式下的任何时间查询操纵杆端口的当前状态。

ikbd 对操纵杆查询的响应是三个字节的报告,形式如下

0xFD                ; joystick report header
%x000yyyy           ; Joystick 0
%x000yyyy           ; Joystick 1
                    ; where x is the trigger
                    ; and yyy is the stick position

4.4.3. 操纵杆监控

有一种模式可以将几乎所有的键盘通信时间都用于以用户可指定速率报告操纵杆端口的状态。它将保持在此模式,直到重置或命令进入另一种模式。此模式下的 PAUSE 命令不仅停止输出,还暂时停止扫描操纵杆(不排队采样)。

4.4.4. Fire Button 监控

提供一种模式,允许以高速率监控单个输入位。在此模式下,ikbd 以串行通信通道允许的最大速率监控操纵杆 1 发射按钮的状态。数据以每字节 8 位打包,以便传输到主机。 ikbd 将保持在此模式,直到重置或命令进入另一种模式。此模式下的 PAUSE 命令不仅停止输出,还暂时停止扫描按钮(不排队采样)。

4.4.5. 操纵杆键码模式

可以命令 ikbd 将任一操纵杆的使用转换为等效的光标控制按键。 ikbd 提供了一个单断点速度操纵杆光标。操纵杆事件产生按下代码,紧接着是相应光标运动按键的释放代码。操纵杆的触发器或发射按钮会产生高于最大设想的按键矩阵使用的伪按键扫描码(即 JOYSTICK0=0x74, JOYSTICK1=0x75)。

4.5. 实时时钟

ikbd 还维护系统的实时时钟。可以使用命令来设置和查询实时时钟。时间保持维持到一秒的分辨率。

4.6. 状态查询

可以通过发送与 ikbd 设置命令对应的状态查询命令来查找 ikbd 模式和参数的当前状态。

4.7. 启动模式

键盘控制器将在启动时执行一个简单的自检,以检测主要的控制器故障(ROM 校验和和 RAM 测试)以及诸如卡住的按键之类的东西。启动时按下的任何按键都假定为卡住,并返回其 BREAK(原文如此)代码(如果没有前面的 MAKE 代码,则是键盘错误的标志)。如果控制器自检在没有错误的情况下完成,则返回代码 0xF0。(此代码将用于指示 ikbd 控制器的版本/发布。ikbd 的第一个版本是版本 0xF0,如果有第二个版本,它将是 0xF1,依此类推。)ikbd 默认为鼠标位置报告,在任一轴上的阈值为 1 个单位,并且 Y=0 原点位于屏幕顶部,操纵杆 1 采用操纵杆事件报告模式,并且两个按键都逻辑上分配给鼠标。在任何操纵杆命令之后,ikbd 都假定操纵杆已连接到 Joystick0 和 Joystick1。然后,任何鼠标命令(除了 MOUSE DISABLE)都会再次导致端口 0 被扫描,就像它是一个鼠标一样,并且两个按键都逻辑上连接到它。如果在假定端口 0 是鼠标时收到鼠标禁用命令,则该按键在逻辑上分配给 Joystick1(直到通过另一个鼠标命令重新启用鼠标)。

4.8. ikbd 命令集

本节包含可以发送到 ikbd 的命令列表。未指定的命令代码(例如 0x00)不应执行任何操作(NOP)。

4.8.1. RESET

0x80
0x01

注意:RESET 命令是 ikbd 唯一理解的两字节命令。除了 0x01 之外,任何跟在 0x80 命令字节之后的字节都会被忽略(并导致 0x80 被忽略)。也可以通过向 ikbd 发送至少持续 200 毫秒的断开来导致重置。执行 RESET 命令会将键盘恢复到其默认(启动)模式和参数设置。它不影响实时时钟。 RESET 命令或函数会导致 ikbd 执行一个简单的自检。如果测试成功,ikbd 将在收到 RESET 命令(或断开结束,或启动)后的 300 毫秒内发送代码 0xF0。然后,ikbd 将扫描按键矩阵以查找任何卡住(闭合)的按键。任何发现闭合的按键都会导致生成断开扫描码(没有在按下代码之前的到达的断开代码是按键矩阵错误的标志)。

4.8.2. SET MOUSE BUTTON ACTION

0x07
%00000mss           ; mouse button action
                    ;       (m is presumed = 1 when in MOUSE KEYCODE mode)
                    ; mss=0xy, mouse button press or release causes mouse
                    ;  position report
                    ;  where y=1, mouse key press causes absolute report
                    ;  and x=1, mouse key release causes absolute report
                    ; mss=100, mouse buttons act like keys

此命令设置 ikbd 应如何处理鼠标上的按键。默认的鼠标按键操作模式是 %00000000,按键在逻辑上被视为鼠标的一部分。当按键像按键一样工作时,LEFT=0x74 & RIGHT=0x75。

4.8.3. SET RELATIVE MOUSE POSITION REPORTING

0x08

设置相对鼠标位置报告。(DEFAULT) 每当任一轴上的运动超过可设置的阈值(请参阅 SET MOUSE THRESHOLD)时,ikbd 异步生成鼠标位置数据包。根据鼠标按键模式,当按下或释放任一鼠标按键时,也可能会生成鼠标位置报告。否则,鼠标按键的行为就像它们是键盘按键一样。

4.8.4. SET ABSOLUTE MOUSE POSITIONING

0x09
XMSB                ; X maximum (in scaled mouse clicks)
XLSB
YMSB                ; Y maximum (in scaled mouse clicks)
YLSB

设置绝对鼠标位置维护。重置 ikbd 维护的 X 和 Y 坐标。在此模式下,内部维护的坐标的值不会在 0 和较大的正数之间回绕。低于 0 的过度运动将被忽略。该命令设置可以在缩放坐标系中达到的最大正值。超出该值的运动也会被忽略。

4.8.5. SET MOUSE KEYCODE MODE

0x0A
deltax              ; distance in X clicks to return (LEFT) or (RIGHT)
deltay              ; distance in Y clicks to return (UP) or (DOWN)

设置鼠标监控例程以返回光标运动键码,而不是 RELATIVE 或 ABSOLUTE 运动记录。在鼠标行程超过任一轴上的用户指定增量后,ikbd 将返回适当的光标键码。当键盘处于按键扫描码模式时,鼠标运动将导致按下代码,紧接着是释放代码。请注意,此命令不受鼠标运动原点的影响。

4.8.6. SET MOUSE THRESHOLD

0x0B
X                   ; x threshold in mouse ticks (positive integers)
Y                   ; y threshold in mouse ticks (positive integers)

此命令设置在生成鼠标事件之前的阈值。请注意,它不会影响返回给主机的数据的分辨率。此命令仅在 RELATIVE MOUSE POSITIONING 模式下有效。阈值在 RESET(或启动)时默认为 1。

4.8.7. SET MOUSE SCALE

0x0C
X                   ; horizontal mouse ticks per internal X
Y                   ; vertical mouse ticks per internal Y

此命令设置 ABSOLUTE MOUSE POSITIONING 模式的比例因子。在此模式下,必须发生指定数量的鼠标相位变化(“点击”),然后内部维护的坐标才会改变 1(每个轴独立缩放)。请记住,除非已命令 ikbd 报告按键按下或释放(请参阅 SET MOUSE BUTTON ACTION),否则只有通过在 ABSOLUTE MOUSE POSITIONING 模式下查询 ikbd 才能获得鼠标位置信息。

4.8.8. INTERROGATE MOUSE POSITION

0x0D
Returns:
        0xF7       ; absolute mouse position header
BUTTONS
        0000dcba   ; where a is right button down since last interrogation
                   ; b is right button up since last
                   ; c is left button down since last
                   ; d is left button up since last
        XMSB       ; X coordinate
        XLSB
        YMSB       ; Y coordinate
        YLSB

无论 MOUSE BUTTON ACTION 的设置如何,INTERROGATE MOUSE POSITION 命令在 ABSOLUTE MOUSE POSITIONING 模式下都有效。

4.8.9. LOAD MOUSE POSITION

0x0E
0x00                ; filler
XMSB                ; X coordinate
XLSB                ; (in scaled coordinate system)
YMSB                ; Y coordinate
YLSB

此命令允许用户预设内部维护的绝对鼠标位置。

4.8.10. SET Y=0 AT BOTTOM

0x0F

对于所有相对或绝对鼠标运动,此命令使 Y 轴的原点位于 ikbd 内部逻辑坐标系的底部。这会导致朝向用户的鼠标运动在符号上为负,而远离用户的鼠标运动在符号上为正。

4.8.11. SET Y=0 AT TOP

0x10

对于所有相对或绝对鼠标运动,使 Y 轴的原点位于 ikbd 内部逻辑坐标系的顶部。(DEFAULT)这会导致朝向用户的鼠标运动在符号上为正,而远离用户的鼠标运动在符号上为负。

4.8.12. RESUME

0x11

恢复向主机发送数据。由于 ikbd 在其输出已暂停后收到的任何命令也会导致隐式的 RESUME,因此可以将此命令视为 NO OPERATION 命令。如果 ikbd 收到此命令并且未 PAUSED,则会忽略该命令。

4.8.13. DISABLE MOUSE

0x12

禁用所有鼠标事件报告(并且扫描可能在内部被禁用)。任何有效的鼠标模式命令都会恢复鼠标运动监控。(有效的鼠标模式命令是 SET RELATIVE MOUSE POSITION REPORTING、SET ABSOLUTE MOUSE POSITIONING 和 SET MOUSE KEYCODE MODE。)注意:如果已命令鼠标按键像键盘按键一样工作,则此命令确实会影响它们的操作。

4.8.14. PAUSE OUTPUT

0x13

停止向主机发送数据,直到收到另一个有效命令。按键矩阵活动仍在监控中,并且扫描码或 ASCII 字符已排队(达到微控制器支持的最大值),以便在主机允许恢复输出时发送。如果在 JOYSTICK EVENT REPORTING 模式下,操纵杆事件也会排队。鼠标运动应在输出暂停时累积。如果 ikbd 处于 RELATIVE MOUSE POSITIONING REPORTING 模式,则超出正常阈值限制的运动会被累积,以产生传输恢复输出所需的最小数据包数。如果鼠标处于 RELATIVE MOUSE POSITION REPORTING 模式,则按下或释放任一鼠标按键会导致任何累积的运动立即排队为数据包。由于微控制器内存的限制,应谨慎使用此命令,并且输出不应关闭超过 <待定> 毫秒的时间。输出仅在当前“偶数”的末尾停止。如果在多字节报告的中间收到 PAUSE OUTPUT 命令,数据包仍将被传输到结束,然后 PAUSE 将生效。当 ikbd 处于 JOYSTICK MONITORING 模式或 FIRE BUTTON MONITORING 模式时,PAUSE OUTPUT 命令也会暂时停止监控过程(即,不会将样本排队以便传输)。

4.8.15. SET JOYSTICK EVENT REPORTING

0x14

进入 JOYSTICK EVENT REPORTING 模式 (DEFAULT)。操纵杆开关或触发器的每次打开或关闭都会导致生成一个操纵杆事件记录。

4.8.16. SET JOYSTICK INTERROGATION MODE

0x15

禁用 JOYSTICK EVENT REPORTING。主机必须发送单独的 JOYSTICK INTERROGATE 命令来感知操纵杆状态。

4.8.17. JOYSTICK INTERROGATE

0x16

返回一条记录,指示操纵杆的当前状态。此命令在 JOYSTICK EVENT REPORTING 模式或 JOYSTICK INTERROGATION MODE 下均有效。

4.8.18. SET JOYSTICK MONITORING

0x17
rate                ; time between samples in hundredths of a second
Returns: (in packets of two as long as in mode)
        %000000xy   ; where y is JOYSTICK1 Fire button
                    ; and x is JOYSTICK0 Fire button
        %nnnnmmmm   ; where m is JOYSTICK1 state
                    ; and n is JOYSTICK0 state

设置 ikbd 为仅执行监控串行命令行、维护实时时钟和监控操纵杆。速率设置操纵杆样本之间的间隔。注意:用户不应将速率设置得高于串行通信通道允许传输 2 字节数据包的速率。

4.8.19. SET FIRE BUTTON MONITORING

0x18
Returns: (as long as in mode)
        %bbbbbbbb   ; state of the JOYSTICK1 fire button packed
                    ; 8 bits per byte, the first sample if the MSB

设置 ikbd 为仅执行监控串行命令行、维护实时时钟和监控操纵杆 1 上的发射按钮。扫描发射按钮的速率会导致在将先前字节发送到主机所需的时间内进行 8 个样本(即,扫描速率 = 8/10 * 波特率)。样本间隔应尽可能恒定。

4.8.20. SET JOYSTICK KEYCODE MODE

0x19
RX                  ; length of time (in tenths of seconds) until
                    ; horizontal velocity breakpoint is reached
RY                  ; length of time (in tenths of seconds) until
                    ; vertical velocity breakpoint is reached
TX                  ; length (in tenths of seconds) of joystick closure
                    ; until horizontal cursor key is generated before RX
                    ; has elapsed
TY                  ; length (in tenths of seconds) of joystick closure
                    ; until vertical cursor key is generated before RY
                    ; has elapsed
VX                  ; length (in tenths of seconds) of joystick closure
                    ; until horizontal cursor keystrokes are generated
                    ; after RX has elapsed
VY                  ; length (in tenths of seconds) of joystick closure
                    ; until vertical cursor keystrokes are generated
                    ; after RY has elapsed

在此模式下,扫描操纵杆 0 的方式会模拟光标按键。在初始闭合时,会生成一个按键对(按下/释放)。然后在最多 Rn 十分之一秒后,每 Tn 十分之一秒生成按键对。在达到 Rn 断点后,每 Vn 十分之一秒生成按键对。这提供了速度(自动重复)断点功能。请注意,通过将 RX 和/或 Ry 设置为零,可以禁用速度功能。然后 TX 和 TY 的值变得毫无意义,并且光标“按键”的生成由 VX 和 VY 设置。

4.8.21. DISABLE JOYSTICKS

0x1A

禁用任何操纵杆事件的生成(并且扫描可能在内部被禁用)。任何有效的操纵杆模式命令都会恢复操纵杆监控。(操纵杆模式命令是 SET JOYSTICK EVENT REPORTING、SET JOYSTICK INTERROGATION MODE、SET JOYSTICK MONITORING、SET FIRE BUTTON MONITORING 和 SET JOYSTICK KEYCODE MODE。)

4.8.22. TIME-OF-DAY CLOCK SET

0x1B
YY                  ; year (2 least significant digits)
MM                  ; month
DD                  ; day
hh                  ; hour
mm                  ; minute
ss                  ; second

所有实时数据都应以压缩 BCD 格式发送到 ikbd。任何不是有效 BCD 数字的数字都应被视为“无关紧要”,并且不会更改日期或时间的特定字段。这允许仅设置实时时钟的一些子字段。

4.8.23. INTERROGATE TIME-OF-DAT CLOCK

0x1C
Returns:
        0xFC        ; time-of-day event header
        YY          ; year (2 least significant digits)
        MM          ; month
        DD          ; day
        hh          ; hour
        mm          ; minute
        ss          ; second

All time-of-day is sent in packed BCD format.

4.8.24. MEMORY LOAD

0x20
ADRMSB              ; address in controller
ADRLSB              ; memory to be loaded
NUM                 ; number of bytes (0-128)
{ data }

此命令允许主机将任意值加载到 ikbd 控制器内存中。数据字节之间的时间必须小于 20 毫秒。

4.8.25. MEMORY READ

0x21
ADRMSB              ; address in controller
ADRLSB              ; memory to be read
Returns:
        0xF6        ; status header
        0x20        ; memory access
        { data }    ; 6 data bytes starting at ADR

此命令允许主机从 ikbd 控制器内存中读取。

4.8.26. CONTROLLER EXECUTE

0x22
ADRMSB              ; address of subroutine in
ADRLSB              ; controller memory to be called

此命令允许主机命令执行 ikbd 控制器内存中的子例程。

4.8.27. STATUS INQUIRIES

Status commands are formed by inclusively ORing 0x80 with the
relevant SET command.

Example:
0x88 (or 0x89 or 0x8A)  ; request mouse mode
Returns:
        0xF6        ; status response header
        mode        ; 0x08 is RELATIVE
                    ; 0x09 is ABSOLUTE
                    ; 0x0A is KEYCODE
        param1      ; 0 is RELATIVE
                    ; XMSB maximum if ABSOLUTE
                    ; DELTA X is KEYCODE
        param2      ; 0 is RELATIVE
                    ; YMSB maximum if ABSOLUTE
                    ; DELTA Y is KEYCODE
        param3      ; 0 if RELATIVE
                    ; or KEYCODE
                    ; YMSB is ABSOLUTE
        param4      ; 0 if RELATIVE
                    ; or KEYCODE
                    ; YLSB is ABSOLUTE
        0           ; pad
        0

STATUS INQUIRY 命令请求 ikbd 返回当前模式或与给定命令关联的参数。所有状态报告都填充为形成 8 字节长的返回数据包。状态请求的响应设计为,主机可以存储它们(在剥离状态报告标头字节之后),然后在稍后将它们发送回 ikbd 以恢复其状态。0 填充字节将被 ikbd 视为 NOP。

有效的 STATUS INQUIRY 命令为

0x87    mouse button action
0x88    mouse mode
0x89
0x8A
0x8B    mnouse threshold
0x8C    mouse scale
0x8F    mouse vertical coordinates
0x90    ( returns       0x0F Y=0 at bottom
                0x10 Y=0 at top )
0x92    mouse enable/disable
        ( returns       0x00 enabled)
                0x12 disabled )
0x94    joystick mode
0x95
0x96
0x9A    joystick enable/disable
        ( returns       0x00 enabled
                0x1A disabled )

程序员(主机)有责任一次只处理一个未完成的查询。如果 ikbd 处于 JOYSTICK MONITORING 模式或 FIRE BUTTON MONITORING 模式,则 STATUS INQUIRY 命令无效。

4.9. 扫描码

由 ikbd 返回的按键扫描码经过选择以简化 GSX 的实现。

GSX 标准键盘映射

十六进制

键帽

01

Esc

02

1

03

2

04

3

05

4

06

5

07

6

08

7

09

8

0A

9

0B

0

0C

-

0D

=

0E

BS

0F

TAB

10

Q

11

W

12

E

13

R

14

T

15

Y

16

U

17

I

18

O

19

P

1A

[

1B

]

1C

RET

1D

CTRL

1E

A

1F

S

20

D

21

F

22

G

23

H

24

J

25

K

26

L

27

;

28

29

`

2A

(左)SHIFT

2B

\

2C

Z

2D

X

2E

C

2F

V

30

B

31

N

32

M

33

,

34

.

35

/

36

(右)SHIFT

37

{ 未使用 }

38

ALT

39

空格键

3A

CAPS LOCK

3B

F1

3C

F2

3D

F3

3E

F4

3F

F5

40

F6

41

F7

42

F8

43

F9

44

F10

45

{ 未使用 }

46

{ 未使用 }

47

HOME (起始位置)

48

UP ARROW (向上箭头)

49

{ 未使用 }

4A

KEYPAD - (小键盘 -)

4B

LEFT ARROW (向左箭头)

4C

{ 未使用 }

4D

RIGHT ARROW (向右箭头)

4E

KEYPAD + (小键盘 +)

4F

{ 未使用 }

50

DOWN ARROW (向下箭头)

51

{ 未使用 }

52

INSERT (插入)

53

DEL (删除)

54

{ 未使用 }

5F

{ 未使用 }

60

ISO KEY (ISO 键)

61

UNDO (撤销)

62

HELP (帮助)

63

KEYPAD ( (小键盘 (

64

KEYPAD / (小键盘 /)

65

KEYPAD * (小键盘 *)

66

KEYPAD * (小键盘 *)

67

KEYPAD 7 (小键盘 7)

68

KEYPAD 8 (小键盘 8)

69

KEYPAD 9 (小键盘 9)

6A

KEYPAD 4 (小键盘 4)

6B

KEYPAD 5 (小键盘 5)

6C

KEYPAD 6 (小键盘 6)

6D

KEYPAD 1 (小键盘 1)

6E

KEYPAD 2 (小键盘 2)

6F

KEYPAD 3 (小键盘 3)

70

KEYPAD 0 (小键盘 0)

71

KEYPAD . (小键盘 .)

72

KEYPAD ENTER (小键盘 Enter)