Skip to content

Apple M0110 Keyboard Protocol

hasu@tmk edited this page Jan 29, 2024 · 20 revisions

Pinouts

Mac 128k/512k/Plus Keyboard pinout
.---------, 
| 1 2 3 4 | 1 GND
|         | 2 Clock
|         | 3 Data
`---___---' 4 5V
from front of connector

Protocol

Keyboard Communication Protocol

The keyboard data line is bidirectional and is driven by whatever device is sending data. The keyboard clock line is driven by the keyboard only. All data transfers are synchronous with the keyboard clock. Each transmission consists of eight bits, with the highestorder bits first.

When sending data to the Macintosh, the keyboard clock transmits eight 330-usec cycles (160 usee low, 170 usee high) on the normally high clock line. It places the data bit on the data line 40 usee before the falling edge of the clock line and maintains it for 330 usee. The data bit is clocked into the Macintosh's VIA shift register on the rising edge of the keyboard clock cycle.

When the Macintosh sends data to the keyboard, the keyboard clock transmits eight 400-usec cycles (180 usee low, 220 usee high) on the clock line. On the falling edge of the keyboard clock cycle, the Macintosh places the data bit on the data line and holds it there for 400 usee. The keyboard reads the data bit 80 usee after the rising edge of the keyboard clock cycle.

Only the Macintosh can initiate communication over the keyboard lines. On power-up of either the Macintosh or the keyboard, the Macintosh is In charge, and the external device is passive. The Macintosh signals that it's ready to begin communication by pulling the keyboard data line low. Upon detecting this, the keyboard starts clocking and the

Macintosh sends a command , The last bit of the command leaves the keyboard data line low; the Macintosh then indicates it's ready to receive the keyboard's response by setting the data line high.

The first command the Macintosh sends out is the Model Number command* The keyboard's response to this command is to reset itself and send back its model number to the Macintosh. If no response is received for 1/2 second, the Macintosh tries the Model Number command again* Once the Macintosh has successfully received a model number from the keyboard, normal operation can begin. The Macintosh sends the Inquiry command; the keyboard sends back a Key Transition response if a key hae been pressed or released. If no key transition has occurred after 1/4 second, the keyboard sends back a Null response to let the Macintosh know it's still there. The Macintosh then sends the Inquiry command again. In normal operation, the Macintosh sends out an Inquiry command every 1/4 second. If it receives no response within 1/2 second, it assumes the keyboard is missing or needs resetting, so it begins again with the Model Number command.

There are two other commands the Macintosh can send: the Instant command, which gets an instant keyboard status without the 1/4-second timeout, and the Test command, to perform a keyboard self-test. Here's a list of the commands that can be sent from the Macintosh to the keyboard:

(See below)

The Key Transition responses are sent out by the keyboard as a single byte: Bit 7 high means a key-up transition, and bit 7 low means a keydown* Bit is always high* The Key Transition responees for key-down transitions on the keyboard are shown (in hexadecimal) in Figure 9. Note that these response codes are different from the key codes returned by the keyboard driver software. The keyboard driver strips off bit 7 of the response and shifts the result one bit to the right, removing bit 0* For example, response code $33 becomes $19, and $2B becomes $15.

(p.20 Apple Macintosh 128K/512K Computer Technical Information)

Keypad Communication Protocol

When a numeric keypad is used, it must be inserted between the keyboard and the Macintosh; that is, the keypad cable plugs into the jack on the front of the Macintosh, and the keyboard cable plugs into a jack on the numeric keypad. In this configuration, the timings and protocol for the clock and data lines work a little differently: The keypad acts like a keyboard when communicating with the Macintosh, and acts like a Macintosh when communicating over the separate clock and data lines going to the keyboard. All commands from the Macintosh are now received by the keypad instead of the keyboard, and only the keypad can communicate directly with the keyboard.

When the Macintosh sends out an Inquiry command, one of two things may happen, depending on the state of the keypad. If no key transitions have occurred on the keypad since the last Inquiry, the keypad sends an Inquiry command to the keyboard and, later, retransmits the keyboard's response back to the Macintosh* But if a key transition has occurred on the keypad, the keypad responds to an Inquiry by sending back the Keypad response ($79) to the Macintosh, In that case, the Macintosh immediately sends an Instant command, and this time the keypad sends back its own Key Transition response. As with the keyboard, bit 7 high means key-up and bit 7 low means key-down.

The Key Transition responses for key-down transitions on the keypad are shown in Figure 9 above. Again, note that these response codes are different from the key codes returned by the keyboard driver software. The keyboard driver strips off bit 7 of the response and shifts theresult one bit to the right, removing bit 0.

(p.23 Apple Macintosh 128K/512K Computer Technical Information)

Command

Inquiry     0x10    get key event with block
Instant     0x12    get key event
Model       0x14    get model number(M0110 responds with 0x09)
Test        0x16    test(ACK:0x7D/NAK:0x77)

Response

Key Event

Raw Code:

bit 7       key state(0:press 1:release)
bit 6-1     scan code(see below)
bit 0       always 1

Model Number

bit 7   1 if another device connected(used when keypad exists?)
bit4-6  next device model number
bit1-3  keyboard model number
bit 0   always 1

Model Code:

Model                   Code    Layout  Made in     Desc
---------------------------------------------------------------------
M0110(GS536)            0x03    US      USA
M0110(GS624)            0x09    US      USA
M0110F                  0x03    French  Ireland     https://github.com/tmk/tmk_keyboard/issues/771
M0110A(M923)            0x0B    US
M0110AJ(M839)           0x0B    US
M0110AJ(A615)           0x0B    US
M0120(BCG9GRM0120)      0x11
M0120 & M0110(G536)     0x13
M0120 & M0110(G624)     0x19
M0120 & M0110A(M923)    0x1B

Signaling

CLOCK is always from KEYBOARD. DATA are sent with MSB first.

1) IDLE: both lines are high.
    CLOCK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    DATA  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

2) KEYBOARD->HOST: HOST reads bit on rising edge.
    CLOCK ~~~~~~~~~~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~~~~~~~~~
    DATA  ~~~~~~~~~~~~X777777X666666X555555X444444X333333X222222X111111X000000X~~~~~~~
                      <--> 160us(clock low)
                         <---> 180us(clock high)

3) HOST->KEYBOARD: HOST asserts bit on falling edge.
    CLOCK ~~~~~~~~~~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~~~~~~~~~
    DATA  ~~~~~~|_____X777777X666666X555555X444444X333333X222222X111111X000000X~~~~~~~
                <----> 840us(request to send by host)                     <---> 80us(hold DATA)
                      <--> 180us(clock low)
                         <---> 220us(clock high)

Raw Codes

M0110 / M0120

m0110_rawcodes

All keys on M0120 keypad are prefixed with 0x79 simply:

press: 0x79, 0xDD
release: 0x79, 0xUU
where DD = <raw code> and UU = <raw code> | 0x80

M0110A

,---------------------------------------------------------. ,---------------.
|  `|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|Bcksp| |Clr|  =|  /|  *|
|---------------------------------------------------------| |---------------|
|Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|   | |  7|  8|  9|  -|
|-----------------------------------------------------'   | |---------------|
|CapsLo|  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;|  '|Return| |  4|  5|  6|  +|
|---------------------------------------------------------| |---------------|
|Shift   |  Z|  X|  C|  V|  B|  N|  M|  ,|  ,|  /|Shft|Up | |  1|  2|  3|   |
|---------------------------------------------------------' |-----------|Ent|
|Optio|Mac    |           Space           |  \|Lft|Rgt|Dn | |      0|  .|   |
`---------------------------------------------------------' `---------------'
,---------------------------------------------------------. ,---------------.
| 65| 25| 27| 29| 2B| 2F| 2D| 35| 39| 33| 3B| 37| 31|   67| |+0F|*11|*1B|*05|
|---------------------------------------------------------| |---------------|
|   61| 19| 1B| 1D| 1F| 23| 21| 41| 45| 3F| 47| 43| 3D|   | |+33|+37|+39|+1D|
|-----------------------------------------------------'   | |---------------|
|    73| 01| 03| 05| 07| 0B| 09| 4D| 51| 4B| 53| 4F|    49| |+2D|+2F|+31|*0D|
|---------------------------------------------------------| |---------------|
|      71| 0D| 0F| 11| 13| 17| 5B| 5D| 27| 5F| 59|  71|+1B| |+27|+29|+2B|   |
|---------------------------------------------------------' |-----------|+19|
|   75|     6F|            63             | 55|+0D|+05|+11| |    +25|+03|   |
`---------------------------------------------------------' `---------------'
[+] press: 0x79, 0xDD / release: 0x79, 0xUU
[*] press: 0x71, 0x79, 0xDD / release: 0xF1, 0x79, 0xUU
where DD = <raw code> and UU = <raw code> | 0x80

On M0110A Keypad keys and Arrow keys are preceded by 0x79 and some of the keys(=, /, * and +) are preceded by 0x71 on press and 0xF1 on release in addtion.

On M0110A note that Arrow keys and Calc keys(+,*,/,= on keypad) share same byte sequence like below. Preceding 0x71 and 0xF1 means press and release event of SHIFT. This causes a very confusing situation, it is difficult or impossible to tell Calc key from Arrow key plus SHIFT in some cases.

      press               release
        ----------------    ----------------
Left:         0x79, 0x0D          0x79, 0x8D
Right:        0x79, 0x05          0x79, 0x85
Up:           0x79, 0x1B          0x79, 0x9B
Down:         0x79, 0x11          0x79, 0x91
Pad+:   0x71, 0x79, 0x0D    0xF1, 0x79, 0x8D
Pad*:   0x71, 0x79, 0x05    0xF1, 0x79, 0x85
Pad/:   0x71, 0x79, 0x1B    0xF1, 0x79, 0x9B
Pad=:   0x71, 0x79, 0x11    0xF1, 0x79, 0x91

Scan Codes

TMK converer uses following scan codes instead of M0110 raw codes. The scan codes are converted from raw codes basically like below. MSB(bit7) is set when key is released.

    scancode = ((raw&0x80) | ((raw&0x7F)>>1))

And keys on keypad are converted exceptionally.

https://github.com/tmk/tmk_keyboard/blob/5208d3165768f93e23e7b46358e1fed252baa241/tmk_core/protocol/m0110.c#L157-L313

M0110 / M0120

,---------------------------------------------------------.    ,---------------.
|  `|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|Backs|    |Clr|  -|Lft|Rgt|
|---------------------------------------------------------|    |---------------|
|Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|  \|    |  7|  8|  9|Up |
|---------------------------------------------------------|    |---------------|
|CapsLo|  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;|  '|Return|    |  4|  5|  6|Dn |
|---------------------------------------------------------|    |---------------|
|Shift   |  Z|  X|  C|  V|  B|  N|  M|  ,|  ,|  /|        |    |  1|  2|  3|   |
`---------------------------------------------------------'    |-----------|Ent|
     |Opt|Mac |         Space               |Enter|Opt|        |      0|  .|   |
     `------------------------------------------------'        `---------------'
,---------------------------------------------------------.    ,---------------.
| 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18|   33|    | 47| 4E| 46| 42|
|---------------------------------------------------------|    |---------------|
|   30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| 2A|    | 59| 5B| 5C| 4D|
|---------------------------------------------------------|    |---------------|
|    39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27|    24|    | 56| 57| 58| 48|
|---------------------------------------------------------|    |---------------|
|      38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C|      38|    | 53| 54| 55|   |
`---------------------------------------------------------'    |-----------| 4C|
     | 3A|  37|             31              |   34| 3A|        |     52| 41|   |
     `------------------------------------------------'        `---------------'

M0110 International

,---------------------------------------------------------.
| 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18|   33|
|---------------------------------------------------------|
|   30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| 2A|
|------------------------------------------------------   |
|    39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27| 24|  |
|---------------------------------------------------------|
|  38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C| 0A|      38|
`---------------------------------------------------------'
     | 3A|  37|             34              |   31| 3A|
     `------------------------------------------------'

M0110A

,---------------------------------------------------------. ,---------------.
|  `|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|Bcksp| |Clr|  =|  /|  *|
|---------------------------------------------------------| |---------------|
|Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|   | |  7|  8|  9|  -|
|-----------------------------------------------------'   | |---------------|
|CapsLo|  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;|  '|Return| |  4|  5|  6|  +|
|---------------------------------------------------------| |---------------|
|Shift   |  Z|  X|  C|  V|  B|  N|  M|  ,|  ,|  /|Shft|Up | |  1|  2|  3|   |
|---------------------------------------------------------' |-----------|Ent|
|Optio|Mac    |           Space           |  \|Lft|Rgt|Dn | |      0|  .|   |
`---------------------------------------------------------' `---------------'
,---------------------------------------------------------. ,---------------.
| 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18|   33| | 47| 68| 6D| 62|
|---------------------------------------------------------| |---------------|
|   30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E|   | | 59| 5B| 5C| 4E|
|-----------------------------------------------------'   | |---------------|
|    39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27|    24| | 56| 57| 58| 66|
|---------------------------------------------------------| |---------------|
|      38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C|  38| 4D| | 53| 54| 55|   |
|---------------------------------------------------------' |-----------| 4C|
|   3A|     37|            31             | 2A| 46| 42| 48| |     52| 41|   |
`---------------------------------------------------------' `---------------'

Technical resources

Discussion thread

Source code

Technical Info for 128K/512K and Plus

Protocol:

Connector:

  • Page 20 of Tech Info for 128K/512K

Signaling:

Raw/Scan codes:

Clone this wiki locally