顯示具有 鍵盤改裝 標籤的文章。 顯示所有文章
顯示具有 鍵盤改裝 標籤的文章。 顯示所有文章

2023年10月12日 星期四

PS/2 Mouse/Keyboard Protocol

說明:為了使用 Trackpoint 控制器,將網路找到的 PS2 介紹文件備份在此,下面連結似為原文出處,但無法開啟。

http://panda.cs.ndsu.nodak.edu/~achapwes/PICmicro/PS2/ps2.htm


PS/2 Mouse/Keyboard Protocol

This article is Copyright 1999, Adam Chapweske

Introduction:

The PS/2 device interface, used by many modern mice and keyboards, was developed by IBM and originally appeared in the IBM Technical Reference Manual.  However, this document has not been printed for many years and as far as I know, there is currently no official publication of this information.  I have not had access to the IBM Technical Reference Manual, so all information on this page comes from my own experiences as well as help from the references listed at the bottom of this page.

This document descibes the interface used by the PS/2 mouse, PS/2 keyboard, and AT keyboard.  I'll cover the physical and electrical interface, as well as the protocol.  If you need higher-level information, such as commands, data packet formats, or other information specific to the keyboard or mouse, I have written separate documents for the two devices:

The PS/2 (AT) Keyboard Interface
The PS/2 Mouse Interface
I also encourage you to check this site's main page for more information related to this topic, including projects, code, and links related to the mouse and keyboard.  Please send an email if you find any mistakes or bad advice on this site.

The Physical Interface:

The physical PS/2 port is one of two styles of connectors:  The 5-pin DIN or the 6-pin mini-DIN.  Both connectors are completely (electrically) similar; the only practical difference between the two is the arrangement of pins.  This means the two types of connectors can easily be changed with simple hard-wired adaptors.  These cost about $6 each or you can make your own by matching the pins on any two connectors.  The DIN standard was created by the German Standardization Organization (Deutsches Institut fuer Norm) .  Their website is at http://www.din.de (this site is in German, but most of their pages are also available in English.)

PC keyboards use either a 6-pin mini-DIN or a 5-pin DIN connector.  If your keyboard has a 6-pin mini-DIN and your computer has a 5-pin DIN (or visa versa), the two can be made compatible with the adaptors described above.  Keyboards with the 6-pin mini-DIN are often referred to as "PS/2" keyboards, while those with the 5-pin DIN are called "AT" devices ("XT" keyboards also used the 5-pin DIN, but they are quite old and haven't been made for many years.)  All modern keyboards built for the PC are either PS/2, AT, or USB.  This document does not apply to USB devices, which use a completely different interface.

Mice come in a number of shapes and sizes (and interfaces.)  The most popular type is probably the PS/2 mouse, with USB mice gaining popularity.  Just a few years ago, serial mice were also quite popular, but the computer industry is abandoning them in support of USB and PS/2 devices.  This document applies only to PS/2 mice.  If you want to interface a serial or USB mouse, there's plenty of information available elsewhere on the web.

The cable connecting the keyboard/mouse to the computer is usually about six feet long and consists of four to six 26 AWG wires surrounded by a thin layer of mylar foil sheilding.  If you need a longer cable, you can buy PS/2 extenstion cables from most consumer electronics stores.  You should not connect multiple extension cables together.  If you need a 30-foot keyboard cable, buy a 30-foot keyboard cable.  Do not simply connect five 6-foot cables together.  Doing so could result in poor communication between the keyboard/mouse and the host.

As a side note, there is one other type of connector you may run into on keyboards. While most keyboard cables are hard-wired to the keyboard, there are some whose cable is not permanently attached and come as a separate component.  These cables have a DIN connector on one end (the end that connects to the computer) and a SDL (Sheilded Data Link) connector on the keyboard end.  SDL was created by a company called "AMP."  This connector is somewhat similar to a telephone connector in that it has wires and springs rather than pins, and a clip holds it in place.  If you need more information on this connector, you might be able to find it on AMP's website at http://www.connect.amp.com.  I have only seen this type of connector on (old) XT keyboards, although there may be AT keyboards that also use the SDL.  Don't confuse the SDL connector with the USB connector--they probably both look similar in my diagram below, but they are actually very different.  Keep in mind that the SDL connector has springs and moving parts, while the USB connector does not.

The pinouts for each connector are shown below:
 

Male

(Plug)
Female 

(Socket)
5-pin DIN (AT/XT): 
1 - Clock
2 - Data
3 - Not Implemented
4 - Ground
5 - Vcc (+5V)


Male

(Plug)
Female

(Socket)
6-pin Mini-DIN (PS/2):
1 - Data
2 - Not Implemented
3 - Ground
4 - Vcc (+5V)
5 - Clock
6 - Not Implemented


 

6-pin SDL:
A - Not Implemented
B - Data
C - Ground
D - Clock
E - Vcc (+5V)
F - Not Implemented


The Electrical Interface:

Note:  Throughout this document, I will use the more general term "host" to refer to the computer--or whatever the keyboard/mouse is connected to-- and the term "device" will refer to the keyboard/mouse.

Vcc/Ground provide power to the keyboard/mouse.  The keyboard or mouse should not draw more than 100 mA from the host and care must be taken to avoid transient surges.  Such surges can be caused by "hot-plugging" a keyboard/mouse (ie, connect/disconnect the device while the computer's power is on.)  Older motherboards had a surface-mounted fuse protecting the keyboard and mouse ports.  When this fuse blew, the motherboard was useless to the consumer, and non-fixable to the average technician.  Most newer motherboards use auto-reset "Poly" fuses that go a long way to remedy this problem.  However, this is not a standard and there's still plenty of older motherboards in use.  Therefore, I recommend against hot-plugging a PS/2 mouse or keyboard.

Summary: Power Specifications
Vcc = +5V.  
Max Current = 100 mA.

The Data and Clock lines are both open-collector with pullup resistors to +5V.  An "open-collector" interface has two possible state: low, or high impedance.  In the "low" state, a transistor pulls the line to ground level.  In the "high impedance" state, the interface acts as an open circuit and doesn't drive the line low or high. Furthermore, a "pullup" resistor is connected between the bus and Vcc so the bus is pulled high if none of the devices on the bus are actively pulling it low.  The exact value of this resistor isn't too important (1~10 kOhms); larger resistances result in less power consumption and smaller resistances result in a faster rise time.  A general open-collector interface is shown below:

Figure 1: General open-collector interface.  Data and Clock are read on the microcontroller's pins A and B, respectively.  Both lines are normally held at +5V, but can be pulled to ground by asserting logic "1" on C and D.  As a result, Data equals D, inverted, and Clock equals C, inverted.


Note: When looking through examples on this website, you'll notice I use a few tricks when implementing an open-collector interface with PIC microcontrollers.  I use the same pin for both input and output, and I enable the PIC's internal pullup resistors rather than using external resistors.  A line is pulled to ground by setting the corresponding pin to output, and writing a "zero" to that port.  The line is set to the "high impedance" state by setting the pin to input.  Taking into account the PIC's built-in protection diodes and sufficient current sinking, I think this is a valid configuration.  Let me know if your experiences have proved otherwise.

Communication: General Description

The PS/2 mouse and keyboard implement a bidirectional synchronous serial protocol.  The bus is "idle" when both lines are high (open-collector).  This is the only state where the keyboard/mouse is allowed begin transmitting data.  The host has ultimate control over the bus and may inhibit communication at any time by pulling the Clock line low.  

The device always generates the clock signal.  If the host wants to send data, it must first inhibit communication from the device by pulling Clock low.  The host then pulls Data low and releases Clock.  This is the "Request-to-Send" state and signals the device to start generating clock pulses.

Summary: Bus States
Data = high, Clock = high:  Idle state.
Data = high, Clock = low:  Communication Inhibited.
Data = low, Clock = high:  Host Request-to-Send

  All data is transmitted one byte at a time and each byte is sent in a frame consisting of 11-12 bits.  These bits are:
  • 1 start bit.  This is always 0.
  • 8 data bits, least significant bit first.
  • 1 parity bit (odd parity).
  • 1 stop bit.  This is always 1.
  • 1 acknowledge bit (host-to-device communication only)

The parity bit is set if there is an even number of 1's in the data bits and reset (0) if there is an odd number of 1's in the data bits.  The number of 1's in the data bits plus the parity bit always add up to an odd number (odd parity.)  This is used for error detection.  The keyboard/mouse must check this bit and if incorrect it should respond as if it had received an invalid command.

Data sent from the device to the host is read on the falling edge of the clock signal; data sent from the host to the device is read on the rising edge.  The clock frequency must be in the range 10 - 16.7 kHz.  This means clock must be high for 30 - 50 microseconds and low for 30 - 50 microseconds..  If you're designing a keyboard, mouse, or host emulator, you should modify/sample the Data line in the middle of each cell.  I.e.  15 - 25 microseconds after the appropriate clock transition.  Again, the keyboard/mouse always generates the clock signal, but the host always has ultimate control over communication.

Timing is absolutely crucial.  Every time quantity I give in this article must be followed exactly.

Communication: Device-to-Host

The Data and Clock lines are both open collector.  A resistor is connected between each line and +5V, so the idle state of the bus is high. When the keyboard or mouse wants to send information, it first checks the Clock line to make sure it's at a high logic level.  If it's not, the host is inhibiting communication and the device must buffer any to-be-sent data until the host releases Clock.  The Clock line must be continuously high for at least 50 microseconds before the device can begin to transmit its data. 

As I mentioned in the previous section, the keyboard and mouse use a serial protocol with 11-bit frames.  These bits are:

  • 1 start bit.  This is always 0.
  • 8 data bits, least significant bit first.
  • 1 parity bit (odd parity).
  • 1 stop bit.  This is always 1.
The keyboard/mouse writes a bit on the Data line when Clock is high, and it is read by the host when Clock is low.  Figures 2 and 3 illustrate this.

Figure 2:  Device-to-host communication.  The Data line changes state when Clock is high and that data is valid when Clock is low.

Figure 3:  Scan code for the "Q" key (15h) being sent from a keyboard to the computer.  Channel A is the Clock signal; channel B is the Data signal.

The clock frequency is 10-16.7 kHz.  The time from the rising edge of a clock pulse to a Data transition must be at least 5 microseconds.  The time from a data transition to the falling edge of a clock pulse must be at least 5 microseconds and no greater than 25 microseconds. 

The host may inhibit communication at any time by pulling the Clock line low for at least 100 microseconds.  If a transmission is inhibited before the 11th clock pulse, the device must abort the current transmission and prepare to retransmit the current "chunk" of data when host releases Clock.  A "chunk" of data could be a make code, break code, device ID, mouse movement packet, etc.  For example, if a keyboard is interrupted while sending the second byte of a two-byte break code, it will need to retransmit both bytes of that break code, not just the one that was interrupted.

If the host pulls clock low before the first high-to-low clock transition, or after the falling edge of the last clock pulse, the keyboard/mouse does not need to retransmit any data.  However, if new data is created that needs to be transmitted, it will have to be buffered until the host releases Clock.  Keyboards have a 16-byte buffer for this purpose.  If more than 16 bytes worth of keystrokes occur, further keystrokes will be ignored until there's room in the buffer.  Mice only store the most current movement packet for transmission.

Host-to-Device Communication:

The packet is sent a little differently in host-to-device communication...

First of all, the PS/2 device always generates the clock signal.  If the host wants to send data, it must first put the Clock and Data lines in a "Request-to-send" state as follows:

  • Inhibit communication by pulling Clock low for at least 100 microseconds.
  • Apply "Request-to-send" by pulling Data low, then release Clock.
The device should check for this state at intervals not to exceed 10 milliseconds.  When the device detects this state, it will begin generating Clock signals and clock in eight data bits and one stop bit.  The host changes the Data line only when the Clock line is low, and data is read by the device when Clock is high.  This is opposite of what occours in device-to-host communication.

After the stop bit is received, the device will acknowledge the received byte by bringing the Data line low and generating one last clock pulse.  If the host does not release the Data line after the 11th clock pulse, the device will continue to generate clock pulses until the the Data line is released (the device will then generate an error.)

The host may abort transmission at time before the 11th clock pulse (acknowledge bit) by holding Clock low for at least 100 microseconds.

To make this process a little easier to understand, here's the steps the host must follow to send data to a PS/2 device:

1)   Bring the Clock line low for at least 100 microseconds.
2)   Bring the Data line low.
3)   Release the Clock line.
4)   Wait for the device to bring the Clock line low.
5)   Set/reset the Data line to send the first data bit
6)   Wait for the device to bring Clock high.
7)   Wait for the device to bring Clock low.
8)   Repeat steps 5-7 for the other seven data bits and the parity bit
9)   Release the Data line.
10) Wait for the device to bring Data low.
11) Wait for the device to bring Clock  low.
12) Wait for the device to release Data and Clock


Figure 3 shows this graphically and Figure 4 separates the timing to show which signals are generated by the host, and which are generated by the PS/2 device.  Notice the change in timing for the "ack" bit--the data transition occours when the Clock line is high (rather than when it is low as is the case for the other 11 bits.)

Figure 3:  Host-to-Device Communication.

Figure 4:  Detailed host-to-device communication.

Referring to Figure 4, there's two time quantities the host looks for.  (a) is the time it takes the device to begin generating clock pulses after the host initially takes the Clock line low, which must be no greater than 15 ms. (b) is the time it takes for the  packet to be sent, which must be no greater than 2ms.  If either of these time limits is not met, the host should generate an error.  Immediately after the "ack" is received, the host may bring the Clock line low to inhibit communication while it processes data.  If the command sent by the host requires a response, that response must be received no later than 20 ms after the host releases the Clock line.  If this does not happen, the host generates an error.

    Other Sources / References:


    The PS/2 Mouse Interface

      

    The PS/2 Mouse Interface
    This article is Copyright 2001, Adam Chapweske 

    Electrical Interface / Protocol:

    The PS/2 mouse uses the same protocol as the PS/2 (AT) keyboard.  This standard originally appeared in the IBM technical reference manual, but I am not aware of any current official publication of this standard.  However, you may click here for the (detailed) information I have gathered about that protocol.

    Inputs, Resolution, and Scaling:

    The standard PS/2 mouse supports the following inputs: X (right/left) movement, Y (up/down) movement, left button, middle button, and right button. The mouse reads these inputs at a regular freqency and updates various counters and flags to reflect movement and button states.  There are many PS/2 pointing devices that have additional inputs and may report data differently than described in this document.  One popular extension I cover later in this document is the Microsoft Intellimouse, which includes support for the standard inputs as well as a scrolling wheel and two additional buttons.

    The standard mouse has two counters that keep track of movement: the X-movement counter and the Y-movement counter.  These  are 9-bit 2's complement values and each has an associated overflow flag.  Their contents, along with the state of the three mouse buttons, are sent to the host in the form of a 3-byte movement data packet (as described in the next section.)  The movement counters represent the amount of movement that has occurred since the last movment data packet was sent to the host.

    When the mouse reads its inputs, it records the current state of its buttons, then checks for movement. If movement has occurred, it increments (for +X or +Y movement) or decrements (for -X or -Y movement) its X and/or Y movement counters. If either of the counters has overflowed, it sets the appropriate overflow flag.

    The parameter that determines the amount by which the movement counters are incremented/decremented is the resolution. The default resolution is 4 counts/mm and the host may change that value using the "Set Resolution" (0xE8) command.

    There is a parameter that does not effect the movement counters, but does effect the reported(1) value of these counters.  This parameter is scaling.  By default, the mouse uses 1:1 scaling, which has no effect on the reported mouse movement.  However, the host may select 1:2 scaling by sending the "Set Scaling 2:1" (0xE7) command.  If 2:1 scaling is enabled, the mouse will apply the following algorithm to the counters before sending their contents to the host:
     
     

    Movement Counter
    Reported Movement
    0
    0
    1
    1
    2
    1
    3
    3
    4
    6
    5
    9
    N > 5
    2 * N

    Movement Data Packet:

    The standard PS/2 mouse sends movement (and button) information to the host using the following 3-byte packet (4):

     

    Byte 1 
    Bit 7
    Bit 6
    Bit 5
    Bit 4
    Bit 3
    Bit 2
    Bit 1
    Bit 0
    Y overflow
    X overflow
    Y sign bit
    X sign bit
    Always 1
    Middle Btn
    Right Btn
    Left Btn
    Byte 2
    X Movement
    Byte 3 
    Y Movement
    The movement counters are 9-bit 2's complement integers, where the most significant bit appears as a sign bit in Byte 1 of the movement data packet. These counters are updated when the mouse reads its input and finds movement has occurred. Their value is the amount of movement that has occurred since the last movement data packet was sent to the host (ie, after a packet is sent to the host, the movement counters are reset.) The range of values that can be expressed by the movement counters is -255 to +255. If this range is exceeded, the appropriate overflow bit is set and the counter is not incremented/decremented until it is reset.

    As I mentioned earlier, the movement counters are reset whenever a movement data packet is successfully sent to the host. They are also reset after the mouse receives any command from the host other than the "Resend" (0xFE) command.

    Modes of Operation:

    Data reporting is handled according to the mode in which the mouse is operating.  There are four standard modes of operation: 

    • Reset - The mouse enters Reset mode at power-up or after receiving the "Reset" (0xFF) command. 
    • Stream - This is the default mode (after Reset finishes executing) and is the mode in which most software uses the mouse.  If the host has previously set the mouse to Remote mode, it may re-enter Stream mode by sending the "Set Stream Mode" (0xEA) command to the mouse. 
    • Remote - Remote mode is useful in some situations and may be entered by sending the "Set Remote Mode" (0xF0) command to the mouse. 
    • Wrap - This mode isn't particularly useful except for testing the connection between the mouse and its host.  Wrap mode may be entered by sending the "Set Wrap Mode" (0xEE) command to the mouse.  To exit Wrap mode, the host must issue the "Reset" (0xFF) command or "Reset Wrap Mode" (0xEC) command.  If the "Reset" (0xFF) command is recieved, the mouse will enter Reset mode.  If the "Reset Wrap Mode" (0xEC) command is received, the mouse will enter the mode it was in prior to Wrap Mode.
    (Note: The mouse may also enter "extended" modes of operation, as described later in this document.  However, this is not a feature of the standard PS/2 mouse.)

    Reset Mode:

    The mouse enters reset mode at power-on or in response to the "Reset" (0xFF) command. After entring this mode, the mouse performs a diagnostic self-test referred to as BAT (Basic Assurance Test) and sets the follwing default values:

    • Sample Rate - 100 samples/sec
    • Resolution - 4 counts/mm
    • Scaling - 1:1
    • Data Reporting Disabled
    It then sends a BAT completion code of either 0xAA (BAT successful) or 0xFC (Error). If the host receives a response other than 0xAA, it may cycle the mouse's power supply, causing the mouse to reset and re-execute its BAT.

    Following the BAT completion code (0xAA or 0xFC), the mouse sends its device ID of 0x00. This distinguishes it from a keyboard, or a mouse in an extended mode. I have read documents saything the host is not supposed to transmit any data until it receives a device ID.  However I've found that some BIOS's will send the "Reset" (0xFF) command immediately following the 0xAA received after a power-on reset.

    After the mouse has sent its device ID to the host, it will enter Stream Mode.  Note that one of the default values set by the mouse is "Data Reporting Disabled".  This means the mouse will not send any movement data packets to the host until the "Enable Data Reporting" (0xF4) command is received.

    Stream Mode:

    In stream mode, the mouse sends movement data when it detects movement or a change in state of one or more mouse buttons. The maximum rate at which this data reporting may occur is known as the sample rate.  This parameter ranges from 10 samples/sec to 200 samples/sec. Its default value is 100 samples/sec and the host may change that value by using the "Set Sample Rate" (0xF3) command.  Stream mode is the default mode of operation.

    Remote Mode:

    In this mode, the mouse reads its inputs and updates its counters/flags at the current sampling rate, but it only notifies the host of movement (and change in button state) when that information is requested by the host. The host does this by issuing the "Read Data" (0xEB) command. After receiveing this command, the mouse will send a movement data packet, and reset its movement counters.

    Wrap Mode:

    This is an "echoing" mode in which every byte received by the mouse is sent back to the host. Even if the byte represents a valid command, the mouse will not respond to that command--it will only echo that byte back to the host. There are two exceptions to this: the "Reset" (0xFF) command and "Reset Wrap Mode" (0xEC) command. The mouse treats these as valid commands and does not echo them back to the host.

    Intellimouse Extensions:

    A popular extension to the standard PS/2 mouse is the Microsoft Intellimouse.  This includes support for a total of five mouse buttons and three axises of movement (right-left, up-down, and a scrolling wheel).  These additional features require the use of a 4-byte movement data packet rather than the standard 3-byte packet.  Since standard PS/2 mouse drivers cannot recognize this packet format, the Microsoft Intellimouse is required to operate exactly like a standard PS/2 mouse unless it knows the drivers support the extended packet format.  This way, if a Microsoft Intellimouse is used on a computer which only supports the standard PS/2 mouse, the Microsoft Intellimouse will still function, except for its scrolling wheel and 4th and 5th buttons.

    The Microsoft Intellimouse operates just like a standard PS/2 mouse (ie, it uses a 3-byte movement data packet, responds to all commands in the same way as a standard PS/2 mouse, and reports a device ID of 0x00.)  To enter scrolling wheel mode, the host sends the following command sequence:

    Set sample rate 200
    Set sample rate 100
    Set sample rate 80
    The host then issues the "Get device ID" command (0xF2) and waits for a response.  If a standard PS/2 mouse (ie, non-Intellimouse) is attached, it will respond with a device ID of 0x00.  In this case, the host will recognize the fact that the mouse does have a scrolling wheel and will continue to treat it as a standard PS/2 mouse.  However, if a Microsoft Intellimouse is attached, it will respond with an ID of 0x03.  This tells the host that the attached pointing device has a scrolling wheel and the host will then expect the mouse to use the following 4-byte movement data packet:
     

    Byte 1 
    Bit 7
    Bit 6
    Bit 5
    Bit 4
    Bit 3
    Bit 2
    Bit 1
    Bit 0
    Y overflow
    X overflow
    Y sign bit
    X sign bit
    Always 1
    Middle Btn
    Right Btn
    Left Btn
    Byte 2
    X Movement
    Byte 3 
    Y Movement
    Byte 4
    Z Movement
    Z Movement is a 2's complement number that represents the scrolling wheel's movement since the last data report.  Valid values are in the range of -8 to +7. This means the number is actually represented only by the least significant four bits; the upper four bits act only as sign extension bits.
    To enter scrolling wheel + 5 button mode, the host sends the following command sequence:
    Set sample rate 200
    Set sample rate 200
    Set sample rate 80
    The host then issues the "Get device ID" command (0xF2) and waits for a response.  A Microsoft Intellimouse will respond with a device ID of 0x04, then use the following 4-byte movement data packet:
     

    Byte 1 
    Bit 7
    Bit 6
    Bit 5
    Bit 4
    Bit 3
    Bit 2
    Bit 1
    Bit 0
    Y overflow
    X overflow
    Y sign bit
    X sign bit
    Always 1
    Middle Btn
    Right Btn
    Left Btn
    Byte 2
    X Movement
    Byte 3 
    Y Movement
    Byte 4
    Always 0
    Always 0
    5th Btn
    4th Btn
    Z3
    Z2
    Z1
    Z0
    Z0-Z3 is a 2's complement number which represents the amount of movement that has occurred since the last data report.  Valid values range from -8 to +7.
    4th Btn: 1 = 4th mouse button is pressed; 0 = 4th mouse button is not pressed.
    5th Btn: 1 = 5th mouse button is pressed; 0 = 5th mouse button is not pressed.
    You may have seen mice with two scrolling wheels--one vertical and the other horizontal.  These mice use the Microsoft Intellimouse data packet format as described above.  If the vertical wheel is scrolled upward, the Z-counter is incremented by one and if that wheel is scrolled down, the Z-counter is decremented by one.  This is normal operation for a scrolling wheel.  However, if the horizontal wheel is scrolled right, the Z-counter is incremented by two and if it is scrolled left, the Z-counter is decremented by two.  This seems like an odd way to implement the second scrolling wheel, but it works since the placement of the two wheels make it impossible to use both of them at the same time (and if you try to trick the software and use both at the same time, it will ignore the horizontal wheel.)

    Command Set:

    The following are the only commands that may be sent to the mouse... If the mouse is in Stream mode, the host should disable data reporting (command 0xF5) before sending any other commands...

    • 0xFF (Reset) - The mouse responds to this command with "acknowledge" (0xFA) then enters Reset Mode.
    • 0xFE (Resend) - The host sends this command whenever it receives invalid data from the mouse. The mouse responds by resending the last(2) packet(3) it sent to the host.   If the mouse responds to the "Resend" command with another invalid packet, the host may either issue another "Resend" command, issue an "Error" command, cycle the mouse's power supply to reset the mouse, or it may inhibit communication (by bringing the Clock line low).  The action taken depends on the host.
    • 0xF6 (Set Defaults) - The mouse responds with "acknowledge" (0xFA) then loads the following values:  Sampling rate = 100, Resolution = 4 counts/mm, Scaling = 1:1, Disable Data Reporting.  The mouse then resets its movement counters and enters stream mode.
    • 0xF5 (Disable Data Reporting) - The mouse responds with "acknowledge" (0xFA) then disables data reporting and resets its movement counters.  This only effects data reporting in Stream mode and does not disable sampling.  Disabled stream mode funcions the same as remote mode.
    • 0xF4 (Enable Data Reporting) - The mouse responds with "acknowledge" (0xFA) then enables data reporting and resets its movement counters.  This command may be issued while the mouse is in Remote Mode (or Stream mode), but it will only effect data reporting in Stream mode.
    • 0xF3 (Set Sample Rate) - The mouse responds with "acknowledge" (0xFA) then reads one more byte from the host.  The mouse saves this byte as the new sample rate. After receiving the sample rate, the mouse again responds with "acknowledge" (0xFA) and resets its movement counters.  Valid sample rates are 10, 20, 40, 60, 80, 100, and 200 samples/sec.
    • 0xF2 (Get Device ID) - The mouse responds with "acknowledge" (0xFA) followed by its device ID (0x00 for the standard PS/2 mouse.)  The mouse should also reset its movement counters.
    • 0xF0 (Set Remote Mode) - The mouse responds with "acknowledge" (0xFA) then resets its movement counters and enters remote mode.
    • 0xEE (Set Wrap Mode) - The mouse responds with "acknowledge" (0xFA) then resets its movement counters and  enters wrap mode.
    • 0xEC (Reset Wrap Mode) - The mouse responds with "acknowledge" (0xFA) then resets its movement counters and enters the mode it was in prior to wrap mode (Stream Mode or Remote Mode.)
    • 0xEB (Read Data) - The mouse responds with acknowledge (0xFA) then sends a movement data packet. This is the only way to read data in Remote Mode.  After the data packets has been successfully sent, it resets its movement counters.
    • 0xEA (Set Stream Mode) - The mouse responds with "acknowledge" then resets its movement counters and enters steram mode.
    • 0xE9 (Status Request) - The mouse responds with "acknowledge" then sends the following 3-byte status packet (then resets its movement counters.): 
      •  

        Byte 1 
        Bit 7
        Bit 6
        Bit 5
        Bit 4
        Bit 3
        Bit 2
        Bit 1
        Bit 0
        Always 0
        Mode
        Enable
        Scaling
        Always 0
        Left Btn
        Middle Btn
        Right Btn
        Byte 2
        Resolution
        Byte 3 
        Sample Rate

        Right, Middle, Left Btn = 1 if button pressed; 0 if button is not pressed.
        Scaling = 1 if scaling is 2:1; 0 if scaling is 1:1. (See commands 0xE7 and 0xE6)
        Enable = 1 if data reporting is enabled; 0 if data reporting is disabled. (See commands 0xF5 and 0xF4)
        Mode = 1 if Remote Mode is enabled; 0 if Stream mode is enabled. (See commands 0xF0 and 0xEA)
         

    • 0xE8 (Set Resolution) - The mouse responds with acknowledge (0xFA) then reads one byte from the host and again responds with acknowledge (0xFA) then resets its movement counters.  The byte read from the host determines the resolution as follows: 
       
      Byte Read from Host
      Resolution
      0x00
      1 count/mm
      0x01
      2 count/mm
      0x02
      4 count/mm
      0x03
      8 count/mm
    • 0xE7 (Set Scaling 2:1) - The mouse responds with acknowledge (0xFA) then enables 2:1 scaling (discussed earlier in this document.)
    • 0xE6 (Set Scaling 1:1) - The mouse responds with acknowledge (0xFA) then enables 1:1 scaling (discussed earlier in this document.)
    The only commands the standard PS/2 mouse will send to the host are the "Resend" (0xFE) and "Error" (0xFC) commands.  They both work the same as they do as host-to-device commands. 

    Initialization:

    The PS/2 mouse is normally detected/initialized only when the computer is booting up.  That is, the mouse is not hot-pluggable and you must restart your computer whenever you add/remove a PS/2 mouse (furthermore, some motherboards may be damaged if you add/remove a PS/2 mouse while the computer is running.)

    The initial detection of the PS/2 mouse occurrs during POST.  If a mouse is detected, the BIOS will allow the operating system to configure/enable the mouse.  Otherwise, it will inhibit communication on the mouse's bus.  If you boot the computer with a mouse attached, then detach/reattach the mouse while in Windows, the OS may be able to detect the mouse was reattached.  Microsoft tried to support this, but it only works about 50% of the time.

    The following is the communication between my computer (running Win98SE) and mouse when it boots up with a standard PS/2 mouse attached.  It is fairly typical of how a PS/2 mouse is initialized and if you want to emulate a PS/2 mouse it must (at minimum) be able to support the following sequence of commands... 

    • Power-on Reset:
      Mouse: AA  Self-test passed
      Mouse: 00  Mouse ID
      Host:  FF  Reset command
      Mouse: FA  Acknowledge
      Mouse: AA  Self-test passed
      Mouse: 00  Mouse ID
      Host:  FF  Reset command
      Mouse: FA  Acknowledge
      Mouse: AA  Self-test passed
      Mouse: 00  Mouse ID
      Host:  FF  Reset command
      Mouse: FA  Acknowledge
      Mouse: AA  Self-test passed
      Mouse: 00  Mouse ID
      Host:  F3  Set Sample Rate   : Attempt to Enter Microsoft
      Mouse: FA  Acknowledge       : Scrolling Mouse mode
      Host:  C8  decimal 200       :
      Mouse: FA  Acknowledge       :
      Host:  F3  Set Sample Rate   :
      Mouse: FA  Acknowledge       :
      Host:  64  decimal 100       :
      Mouse: FA  Acknowledge       :
      Host:  F3  Set Sample Rate   :
      Mouse: FA  Acknowledge       :
      Host:  50  decimal 80        :
      Mouse: FA  Acknowledge       :
      Host:  F2  Read Device Type  :
      Mouse: FA  Acknowledge       :
      Mouse: 00  Mouse ID          : Response 03 if microsoft scrolling mouse
      Host:  F3  Set Sample Rate 
      Mouse: FA  Acknowledge
      Host:  0A  decimal 10
      Mouse: FA  Acknowledge
      Host:  F2  Read Device Type
      Mouse: FA  Acknowledge
      Mouse: 00  Mouse ID
      Host:  E8  Set resolution
      Mouse: FA  Acknowledge
      Host:  03  8 Counts/mm
      Mouse: FA  Acknowledge
      Host:  E6  Set Scaling 1:1
      Mouse: FA  Acknowledge
      Host:  F3  Set Sample Rate
      Mouse: FA  Acknowledge
      Host:  28  decimal 40
      Mouse: FA  Acknowledge
      Host:  F4  Enable
      Mouse: FA  Acknowledge
      Initialization complete...

      If I then press the Left Button...
      Mouse: 09 1 1 00001001; bit0 = Left button state; bit3 = always 1
      Mouse: 00 1 1 No X-movement
      Mouse: 00 1 1 No Y-movement
      ... and release the Left Button:
      Mouse: 08 0 1 00001000 bit0 = Left button state; bit3 = always 1
      Mouse: 00 1 1 No X-movement
      Mouse: 00 1 1 No Y-movement

    The following is the communication between my computer (running Win98SE) and mouse when it boots up with an (emulated) Intellimouse... 
    • Power-on Reset:
      Mouse: AA  Self-test passed
      Mouse: 00  Mouse ID
      Host:  FF  Reset command
      Mouse: FA  Acknowledge
      Mouse: AA  Self-test passed
      Mouse: 00  Mouse ID
      Host:  FF  Reset command
      Mouse: FA  Acknowledge
      Mouse: AA  Self-test passed
      Mouse: 00  Mouse ID
      Host:  FF  Reset command
      Mouse: FA  Acknowledge
      Mouse: AA  Self-test passed
      Mouse: 00  Mouse ID
      Host:  F3  Set Sample Rate   : Attempt to Enter Microsoft 
      Mouse: FA  Acknowledge       : Scrolling Mouse mode
      Host:  C8  decimal 200       :
      Mouse: FA  Acknowledge       :
      Host:  F3  Set Sample Rate   :
      Mouse: FA  Acknowledge       :
      Host:  64  decimal 100       :
      Mouse: FA  Acknowledge       :
      Host:  F3  Set Sample Rate   :
      Mouse: FA  Acknowledge       :
      Host:  50  decimal 80        :
      Mouse: FA  Acknowledge       :
      Host:  F2  Read Device Type  :
      Mouse: FA  Acknowledge       :
      Mouse: 03  Mouse ID          : Response 03 if microsoft scrolling mouse
      Host:  E8  Set Resolution 
      Mouse: FA  Acknowledge 
      Host:  03  8 counts/mm
      Mouse: FA  Acknowledge
      Host:  E6  Set scaling 1:1
      Dev:   FA  Acknowledge
      Host:  F3  Set Sample Rate 
      Mouse: FA  Acknowledge
      Host:  28  decimal 40
      Mouse: FA  Acknowledge
      Host:  F4  Enable device 
      Mouse: FA  Acknowledge

      If I then press the left mouse button:
      Mouse: 09  00001001 bit0 = Left button state; bit3 = always 1
      Mouse: 00  No X-movement
      Mouse: 00  No Y-movement
      Mouse: 00  No Z-movement

      ...and then release the left mouse button button:
      Mouse: 08  00001000 bit0 = Left button state; bit3 = always 1
      Mouse: 00  No X-movement
      Mouse: 00  No Y-movement
      Mouse: 00  No Z-movement

    After I downloaded/installed the Microsoft's Intellimouse drivers with support for the 4th and 5th buttons, the following sequence was found:
    ... (starts same as before) ...
    Host:  F3  Set Sample Rate   : Attempt to Enter Microsoft 
    Mouse: FA  Acknowledge       : Scrolling Mouse mode.
    Host:  C8  decimal 200       :
    Mouse: FA  Acknowledge       :
    Host:  F3  Set Sample Rate   :
    Mouse: FA  Acknowledge       :
    Host:  64  decimal 100       :
    Mouse: FA  Acknowledge       :
    Host:  F3  Set Sample Rate   :
    Mouse: FA  Acknowledge       :
    Host:  50  decimal 80        :
    Mouse: FA  Acknowledge       :
    Host:  F2  Read Device Type  :
    Mouse: FA  Acknowledge       :
    Mouse: 03  Mouse ID          : Response 03 if microsoft scrolling mouse.
    Host:  F3  Set Sample Rate   : Attempt to Enter Microsoft 5-button 
    Mouse: FA  Acknowledge       : Scrolling Mouse mode.
    Host:  C8  decimal 200       :
    Mouse: FA  Acknowledge       :
    Host:  F3  Set Sample Rate   :
    Mouse: FA  Acknowledge       :
    Host:  C8  decimal 200       :
    Mouse: FA  Acknowledge       :
    Host:  F3  Set Sample Rate   :
    Mouse: FA  Acknowledge       :
    Host:  50  decimal 80        :
    Mouse: FA  Acknowledge       :
    Host:  F2  Read Device Type  :
    Mouse: FA  Acknowledge       :
    Mouse: 04  Mouse ID         : Response 04 if 5-button scrolling mouse.
    ... rest of initialization same as before ...
    Emulation/Interfacing:
    • Click here for routines that emulate a PS/2 mouse or keyboard
    • Click here for routines that emulate a PS/2 host (ie, interface a mouse/keyboard)
    • Click here for a fully-functional PS/2 mouse written for the PIC16F84.
    If you want to build a truely fully-implemented mouse or host, you should implement all of the features described in this document (except for, of course, the Microsoft Intellimouse extensions, which are optional).  However, at an absolute minimum, your device should operate as follows:
    To Emulate a Mouse:
    • Never send data when  the "Clock" line low.  If the host pulls the "Data" line low, prepare to read a byte from the host.
    • ~500 milliseconds after powerup, transmit "0xAA, 0x00".
    • Wait for the host to send the enable (0xF4) command before sending any movement/button data.
    • Emulate the various mouse functions as follows:
      Emulated Action
      Data sent to host
      Move up one
      0x08,0x00,0x01
      Move down one
      0x28,0x00,0xFF
      Move right one
      0x08,0x01,0x00
      Move left one
      0x18,0xFF,0x00
      Press left button
      0x09,0x00,0x00
      Release left button
      0x08,0x00,0x00
      Press middle button
      0x0C,0x00,0x00
      Release middle button
      0x08,0x00,0x00
      Press right button
      0x0A,0x00,0x00
      Release right button
      0x08,0x00,0x00
    • Respond to the "Reset" (0xFF) command with "0xFA" then goto the beginning of your program. (ie, send 0xAA, 0x00, then wait for the enable command before sending any movement/button data.)
    • Respond to the "Get Device ID" (0xF2) command with "0xFA, 0x00".
    • Respond to the "Status Request" (0xE9) command with "0xFA, 0x00, 0x02, 0x64".
    • Respond to all other commands with acknowledge (0xFA).
    To Interface a Mouse:
    • Wait for the mouse to send "0xAA", then send the "Enable" (0xF4) command.
    • The mouse will then send a 3-byte movement packets as described earlier in this document.


    Footnotes:

    1) 2:1 scaling only applies to the automatic data reporting in Stream mode. It does not effect the reported data sent in response to the "Read Data" (0xEB) command.

    2)  The mouse and host do not buffer "Resend" (0xFF) commands. This means "0xFE" will never be sent in response to the "Resend" command. 

    3)   A "packet" may be a 3-byte movement data packet, a 4-byte movement data packet (for the Intellimouse), a 3-byte status packet (see "Status Request" [0xE9] command) a 2-byte completion-code-ID packet (0xAA,0x00 or 0xFC,0x00), or a 1-byte response to a command.

    4)  A little advice from my own experience...  Even though bit 3 of the first byte in a movement data packet is supposed to be set, some drivers (such as the standard PS/2 mouse driver included with Windows 98SE) don't care and just ignore that bit.  However, other drivers do check that bit and if it is not set, it is considered an error.  I mention this so that, if you're designing a mouse, you double-check that this bit is set in every movement data packet sent by your mouse.  If it is not, your mouse may work properly when you test it on your computer, but it may not work on other computers that use different mouse drivers. 

    For example, if using MS Intellimouse drivers and bit 3 of the first byte in a movement data packet is not set, the driver will discard that packet, then send the "Disable Data Reporting"  (0xF5) command, followed by the "Set Defaults" (0xF6) command, then it will reinitialize the mouse using the same command sequence as it does when Windows boots up (see the "Initialization" section above.)

    Other Sources / References:


      2023年9月22日 星期五

      STM32 -- 使用 vial 及 vibl

      參考網址 


      必須使用特製的 st-flash,stlink-stm32f10-opt-bytes,提供 "program option bytes" 的功能。其在燒錄 vibl 後,可將對

      From the root of vial-qmk, run python3 util/vial_generate_keyboard_uid.py in order to generate a unique Vial keyboard ID:

      -----------------
      ajax@stm-dev /work/vial-qmk $ python3 util/vial_generate_keyboard_uid.py 
      #define VIAL_KEYBOARD_UID {0xA3, 0xA1, 0xFF, 0x29, 0xE9, 0x28, 0xCC, 0xCC}
      -----------------

      -----------------
      ajax@stm-dev /work $ st-flash opterase
      st-flash 1.5.1
      2023-09-23T08:19:06 INFO usb.c: -- exit_dfu_mode
      2023-09-23T08:19:07 INFO common.c: Loading device parameters....
      2023-09-23T08:19:07 INFO common.c: Device connected is: F1 Medium-density device, id 0x20036410
      2023-09-23T08:19:07 INFO common.c: SRAM size: 0x5000 bytes (20 KiB), Flash: 0x20000 bytes (128 KiB) in pages of 1024 bytes
      2023-09-23T08:19:07 WARN common.c: Unlocking option flash

      ajax@stm-dev /work/vibl/bootloader/build $ st-flash write ../../misc/opt-head.bin 0x1FFFF800
      st-flash 1.5.1
      2023-09-23T08:21:33 INFO common.c: Loading device parameters....
      2023-09-23T08:21:33 INFO common.c: Device connected is: F1 Medium-density device, id 0x20036410
      2023-09-23T08:21:33 INFO common.c: SRAM size: 0x5000 bytes (20 KiB), Flash: 0 bytes (0 KiB) in pages of 1024 bytes
      2023-09-23T08:21:33 WARN common.c: Unlocking option flash

      ajax@stm-dev /work/vibl/bootloader/build $ st-flash write bootloader-magic_tpk_68.bin  0x8000000
      ------------------

      使用 STM32 ST-LINK Utility 比較穩定可靠。另外,必須將開發板的 Boot0 切換到 1 (3.3V),ST-LINK Utility 才能連上。Boot0 不接時,會下拉成 0。但是使用 st-flash 則不用管 Boot0 的位置。

      使用 ST-LINK Utility 寫入的順序如下。

      • opt-default.bin (size: 0x0010) => 0x1FFFF800
      • opt-head.bin (size: 0x0002)  => 0x1FFFF800
      • bootloader-magic_tpk_68.bin => 0x8000000
      • opt-tail.bin => 0x1FFFF802

      在寫入保護之後,假若執行 "Erase Chip",會出現 "Some flash pages are write protected!" 的錯誤。

      再次從 0x8000000 寫入資料會顯示如下的資料。

      09:28:20 : [bootloader-magic_tpk_68.bin] opened successfully.
      09:28:20 : [bootloader-magic_tpk_68.bin] checksum : 0x00043E9E 
      09:28:29 : Some flash sectors are write protected.
                 The write protection will be disabled then restored after flash programming
                 in case there is no option bytes segment within the file.
      09:28:29 : Memory programmed in 0s and 343ms.
      09:28:29 : Verification...OK

      但反覆測試,不太確定正確的該如何做。假如不成功,就試另一種方法吧。


      2023年5月13日 星期六

      阿米洛68鍵盤 -- firmware 修改

       鍵盤型號是 Miya68 Pro,PCB 型號是 Miya69-V2.2 (A)。MCU 上的文字是 HSAK3201 ARM。經過一翻努力追蹤,確定 MCU 是 Holtek 出的 HT32F1654。flash 內容是鎖住的,使用 eLink32Pro.exe 對 flash 執行 mass erase 操作後,就可以讀出晶片的資訊了。

      在 PCB 上焊一個 4pin 的小接頭,pin 腳的間距是 1.24mm,所以要在原來的兩個孔之間再鑽一個小洞。只接了三條線,e-Link32 lite 和鍵盤各自用自己的電源。

      使用 OpenOCD 讀取晶片的資訊。

      設定檔 dap-tst.cfg 如下。因為使用 Ubuntu 的 openocd 套件,沒有HT32F1654 的資訊,先用 stm32f1x 的設定來讀資料。若要寫入資料,則需加入  HT32F1654 的資訊。

      # openocd -f /app/dap-tst.cfg
      adapter driver cmsis-dap
      adapter speed 1000
      transport select swd
      
      source [find target/stm32f1x.cfg]

      執行 openocd 的訊息如下。

      # openocd -f /app/dap-tst.cfg
      Open On-Chip Debugger 0.11.0
      Licensed under GNU GPL v2
      For bug reports, read
      	http://openocd.org/doc/doxygen/bugs.html
      Info : Listening on port 6666 for tcl connections
      Info : Listening on port 4444 for telnet connections
      Info : CMSIS-DAP: SWD  Supported
      Info : CMSIS-DAP: FW Version = 1.0.35
      Info : CMSIS-DAP: Interface Initialised (SWD)
      Info : SWCLK/TCK = 0 SWDIO/TMS = 1 TDI = 0 TDO = 0 nTRST = 0 nRESET = 1
      Info : CMSIS-DAP: Interface ready
      Info : clock speed 1000 kHz
      Info : SWD DPIDR 0x2ba01477
      Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
      Info : starting gdb server for stm32f1x.cpu on 3333
      Info : Listening on port 3333 for gdb connections

      使用 telnet 連上 port 4444,執行 dap info 得到的資訊下。假如還沒解鎖,執行 dap info 會回報錯誤。

      /# telnet localhost 4444
      Trying 127.0.0.1...
      Connected to localhost.
      Escape character is '^]'.
      Open On-Chip Debugger
      > dap info
      
      AP ID register 0x24770011
      	Type is MEM-AP AHB3
      MEM-AP BASE 0xe00ff003
      	Valid ROM table present
      		Component base address 0xe00ff000
      		Peripheral ID 0x0000000000
      		Designer ASCII code 0x00, <unknown>
      		Part is 0x0, Unrecognized 
      		Component class is 0x1, ROM table
      		MEMTYPE system memory present on bus
      	ROMTABLE[0x0] = 0xfff0f003
      		Component base address 0xe000e000
      		Peripheral ID 0x04002bb000
      		Designer is 0x4bb, ARM Ltd
      		Part is 0x0, Cortex-M3 SCS (System Control Space)
      		Component class is 0xe, Generic IP component
      	ROMTABLE[0x4] = 0xfff02003
      		Component base address 0xe0001000
      		Peripheral ID 0x04002bb002
      		Designer is 0x4bb, ARM Ltd
      		Part is 0x2, Cortex-M3 DWT (Data Watchpoint and Trace)
      		Component class is 0xe, Generic IP component
      	ROMTABLE[0x8] = 0xfff03003
      		Component base address 0xe0002000
      		Peripheral ID 0x04002bb003
      		Designer is 0x4bb, ARM Ltd
      		Part is 0x3, Cortex-M3 FPB (Flash Patch and Breakpoint)
      		Component class is 0xe, Generic IP component
      	ROMTABLE[0xc] = 0xfff01003
      		Component base address 0xe0000000
      		Peripheral ID 0x04002bb001
      		Designer is 0x4bb, ARM Ltd
      		Part is 0x1, Cortex-M3 ITM (Instrumentation Trace Module)
      		Component class is 0xe, Generic IP component
      	ROMTABLE[0x10] = 0xfff41003
      		Component base address 0xe0040000
      		Peripheral ID 0x04002bb923
      		Designer is 0x4bb, ARM Ltd
      		Part is 0x923, Cortex-M3 TPIU (Trace Port Interface Unit)
      		Component class is 0x9, CoreSight component
      		Type is 0x11, Trace Sink, Port
      	ROMTABLE[0x14] = 0xfff42002
      		Component not present
      	ROMTABLE[0x18] = 0x0
      		End of ROM table

      由以上的訊息確定 MCU 的核心是 Cortex-M3。

      使用 eLink32Pro.exe  寫入 pok3r-custom/pok3r_re_firmware 的    disassemble/pok3r/builtin/firmware_builtin.bin,連上電腦,顯示的裝置是 

      Bus 001 Device 024: ID 04d9:1141 Holtek Semiconductor, Inc. USB-HID Keyboard

      到此為止,成功解鎖以及寫入下載的 firmware,接下來就是要建立自己的 QMK 鍵盤,以及加上小紅點 (Trackpoint)。




      2023年5月1日 星期一

      阿米洛68鍵盤拆解

      這把從淘寶買回來的垃圾鍵盤,價格還不便宜,接近新台幣一千,但好奇它有什麼好的,還是買來看看。這把的型號是 Miya68 Pro,由 Varmilo 和 Ducky 聯名推出。 

      完全沒有螺絲,所以不要到處找螺絲,把外表都挖壞了。


      這下面沒有螺絲,別挖了。凹痕是灌模的凹孔,這麼貴的東西,會壓成這樣也太不像話了點。鍵盤 PCB 的型號是 Miya69-V2.2 (A)。

      要改裝鍵盤,第一個當然是先看是用什麼晶片,好不容易,用 marco 鏡頭照出比較清晰的型號 -- ARM HSAK3201。


      Google 結果,很多鍵盤用這顆 MCU,但完全沒有相關資訊。最下面的字註明是 ARM CPU,應是 32bit 的 CPU。最後找到這一條訊息,

      Controller: ARM HSAK3201, HOLTEK (via HWInfo)

      Holtek,就是盛群。在鍵盤應用介紹的網頁找到一顆 MCU 的編號 HT66FB576。依據其文件說明,這是一個 USB RGB LED Flash MCU。不過在文件中說,這是一個 "8-bit high performance RISC",所以可能不是這一個 IC。另外有 "多彩獨立光USB鍵盤" 的應用指南。等有空再來比對接腳,看是不是這一顆 CPU。後來也確定不是。

      在這裡可以找到各類相關的開發指南 https://www.holtek.com.tw/professional/usb-mcu

      電路板上有 4顆 24pin 的 IC,編號是 HSAK021,後來比對網上其他鍵盤的拆解說明,應是內建 PWM 的 16bit 恒流 LED driver,如 Macroblock 的 MBI5043,但沒找到 HolTek 出的相關 IC。每個 IC 有 16條 LED 控制輸出,RGB 三種顏色分開控制。不過,我可能會把燈光給廢了吧,不想搞這麼複雜。



      然後,在 pcstore 上找到一家 "倍創科技",專賣 Holtek 的開發工具,其中 32-bit MCU 燒錄器e-Writer32 售價為新台幣 2千多元。後來找到比較便宜的開發板,約 6百元。測試失敗,又花了快一千元買一塊 e-Link32 Pro,做交叉比對,最後都能成功連上。

      比對 "多彩獨立光USB鍵盤" 應用指南與實際量到的電路矩陣,可說是完全使用其參考電路,這倒是比較方便追蹤,不用另外整理按鍵矩陣。

      這鍵盤的固件 (firmware,為了搜尋方便,使用中國用語) 是可以更新的,也許可以在不改電路之下,更改鍵盤功能。參考此文,阿米洛68键双模键盘修改固件调换键位,阿米洛固件更新工具 M32 BootLoader_180724.exe,依命名來看,基本上就是 STM32 的 DFU 寫入程式。後來繼續查下去,確認 M32 BootLoader 是給較舊的鍵盤使用的。Miya68 Pro 的更新程式是把程式和資料包在一個執行檔裡,而且資料可能是加密過的。但是我只要確定使用的 MCU,再改用 QMK,所以不用管它原來的 firmware 長得什麼樣。

      且先不要破壞電路,看能不能有什麼辦法確定使用的 MCU。在 Linux 連上後,列出的訊息如下。

      [  269.812200] usb 1-8.1.2: new full-speed USB device number 9 using xhci_hcd
      [  269.885558] usb 1-8.1.2: device descriptor read/64, error -32
      [  270.065558] usb 1-8.1.2: device descriptor read/64, error -32
      [  270.245532] usb 1-8.1.2: new full-speed USB device number 10 using xhci_hcd
      [  270.336711] usb 1-8.1.2: New USB device found, idVendor=04d9, idProduct=8008, bcdDevice= 2.03
      [  270.336726] usb 1-8.1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
      [  270.336733] usb 1-8.1.2: Product: USB-HID Keyboard
      [  270.336738] usb 1-8.1.2: Manufacturer: HOLTEK
      [  270.336743] usb 1-8.1.2: SerialNumber: AP0000000003
      [  270.352409] input: HOLTEK USB-HID Keyboard as /devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.1/1-8.1.2/1-8.1.2:1.0/0003:04D9:8008.000A/input/input29
      [  270.409145] hid-generic 0003:04D9:8008.000A: input,hidraw5: USB HID v1.11 Keyboard [HOLTEK USB-HID Keyboard] on usb-0000:00:14.0-8.1.2/input0
      [  270.410300] hid-generic 0003:04D9:8008.000B: hiddev97,hidraw6: USB HID v1.11 Device [HOLTEK USB-HID Keyboard] on usb-0000:00:14.0-8.1.2/input1
      [  270.412672] input: HOLTEK USB-HID Keyboard Mouse as /devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.1/1-8.1.2/1-8.1.2:1.2/0003:04D9:8008.000C/input/input30
      [  270.412910] input: HOLTEK USB-HID Keyboard System Control as /devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.1/1-8.1.2/1-8.1.2:1.2/0003:04D9:8008.000C/input/input31
      [  270.469110] input: HOLTEK USB-HID Keyboard Consumer Control as /devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.1/1-8.1.2/1-8.1.2:1.2/0003:04D9:8008.000C/input/input32
      [  270.469257] input: HOLTEK USB-HID Keyboard as /devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.1/1-8.1.2/1-8.1.2:1.2/0003:04D9:8008.000C/input/input33
      [  270.469402] input: HOLTEK USB-HID Keyboard as /devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.1/1-8.1.2/1-8.1.2:1.2/0003:04D9:8008.000C/input/input34
      [  270.469606] hid-generic 0003:04D9:8008.000C: input,hiddev98,hidraw7: USB HID v1.11 Mouse [HOLTEK USB-HID Keyboard] on usb-0000:00:14.0-8.1.2/input2
      [  270.470828] hid-generic 0003:04D9:8008.000D: hiddev99,hidraw8: USB HID v1.11 Device [HOLTEK USB-HID Keyboard] on usb-0000:00:14.0-8.1.2/input3
      lsusb 列出的裝置如下
      # lsusb
      Bus 001 Device 012: ID 04d9:8008 Holtek Semiconductor, Inc. USB-HID Keyboard

      從這些訊息確定是盛群的 IC。

      接下來幾天就跑去合歡山看杜鵑花了。出遊期間,腦袋不時會想著該怎麼做。偶爾上綱找一下資料,發現已經有人針對 Holtek 的 MCU 改過 QMK 了,[Quantum Mechanical Keyboard Firmware for POK3R]。繼續追下去,發現要解鎖 MCU 才能用,又找到了陌生的 OpenOCD。接下來就參雜使用 Holtek 的工具和 OpenOCD,試圖確認鍵盤所使用的 MCU。

      繞一大圈之後,讀了網上高手的逆向工程教學,有一些基本能力後,開始各種嘗試。

      試著使用 HT32 ICP TOOL (V 1.0.39) 來讀取 firmware 的資料,從第一個 target 開始一個一個選,顯示訊息都是 "Target MCU unmatch!"。

      直到倒數沒幾個,接近失望之際,BINGO !  選到 HT32F1654,按下 [Read],顯示訊息變成 "Chip is Locked!"。

      接下來的工作就會變比較簡單了,有前人的作法可以參考。

      HT32F1653, HT32F1654HT32F1655HT32F1656 是同一系列的 MCU -- Cortex-M3 32-Bit Standard MCU,差別在於 Flash 和 SRAM 的大小。HT32F1654 的 Flash 是 64KB,SRAM  是 16KB。

      最後,這顆 MCU 已停產,盛群網上公告的訊息,"Holtek 正式提出 HT32F1653/HT32F1654 產品終止到期。上述所提產品之最終訂單截止日為2022年9月30日"。所以官網上找不到它的 datasheet,只能在其他地方下載。 





      2023年4月30日 星期日

      STM32F103 開發板連接 Trackpoint 測試

      測試硬體

      要改用 STM32F103 開發板來改裝小紅點鍵盤,首先弄個簡單的測試電路來測試連接 trackpoint 的基本功能。小紅點模組不能直接鎖在電路板上,自己用3D印表機打印了一個固定小紅點模組的固定板。


      這塊 trackpoint module 經測試可以使用 3.3V 的電源,但是 DAT 及 CLK 的信號線要用 4.7K 的電阻 pull high  至3.3V。

      關於 trackpoint 的設定檔參考 handwired/trackpoint 的設定。關於 STM32F103 的設定則是參考 doio/kb16/rev2 的設定。

      因為不同的 bootloader 要有不同的設定,為了支援  dfu-util,又重燒 STM32duino-bootloader。直接下載 binary 檔 generic_boot20_pc13.bin 即可,這個檔是指 LED 接在 PC13 的接腳。

      設定檔案

      首先測試簡單的 busywait 運作模式,確認電路連接正常。

      info.json 如下。

      {
          "keyboard_name": "Trackpoint Demo",
          "manufacturer": "QMK",
          "url": "",
          "maintainer": "qmk",
          "usb": {
              "vid": "0x1234",
              "pid": "0x5678",
              "device_version": "0.0.1"
          },
          "processor": "atmega32u4",
          "bootloader": "halfkay",
          "layouts": {
              "LAYOUT": {
                  "layout": [
                      {"x": 0,"y": 0},
                      {"x": 1,"y": 0},
                      {"x": 2,"y": 0}
                  ]
              }
          }
      }

      主要是指定 USB 相關的資訊,compile 時會讀取。vid 和 pid 應是亂設的,使用 lsusb 看到的資訊如下

      Bus 001 Device 026: ID 1234:5678 Brain Actuated Technologies Trackpoint Demo

      rules.mk 如下。內容是抄來的,有些意義不是很了解,但可通過編譯,就留著不管了。

      # MCU name
      MCU = STM32F103
      
      OPT_DEFS += -DBOOTLOADER_STM32DUINO
      MCU_LDSCRIPT = STM32F103xB_stm32duino_bootloader
      BOARD = STM32_F103_STM32DUINO
      
      # Bootloader selection
      BOOTLOADER = custom
      
      # Build Options
      #   change yes to no to disable
      #
      BOOTMAGIC_ENABLE = yes      # Enable Bootmagic Lite
      MOUSEKEY_ENABLE = no        # Mouse keys
      EXTRAKEY_ENABLE = yes       # Audio control and System control
      CONSOLE_ENABLE = no         # Console for debug
      COMMAND_ENABLE = no         # Commands for debug and configuration
      NKRO_ENABLE = yes           # Enable N-Key Rollover
      BACKLIGHT_ENABLE = no       # Enable keyboard backlight functionality
      RGBLIGHT_ENABLE = no        # Enable keyboard RGB underglow
      AUDIO_ENABLE = no           # Audio output
      
      # Enter lower-power sleep mode when on the ChibiOS idle thread
      OPT_DEFS += -DCORTEX_ENABLE_WFI_IDLE=TRUE
      
      PS2_MOUSE_ENABLE = yes
      PS2_ENABLE = yes
      PS2_DRIVER = busywait
      #PS2_DRIVER = interrupt

      先測最簡單的 busywait 運作模式,先把 interrupt 的部分註解掉。

      config.h 如下。只設定了三個按鍵,可以測試鍵盤功能。
      #pragma once
      
      #define MATRIX_COL_PINS { B3, B4, B5 }
      #define MATRIX_ROW_PINS { B0 }
      
      /* COL2ROW or ROW2COL */
      #define DIODE_DIRECTION COL2ROW
      
      #define LOCKING_SUPPORT_ENABLE
      #define LOCKING_RESYNC_ENABLE
      
      #ifdef PS2_DRIVER_BUSYWAIT
        #define PS2_CLOCK_PIN   B8
        #define PS2_DATA_PIN    B9
      
        #define PS2_MOUSE_USE_REMOTE_MODE
      #endif
      
      #ifdef PS2_DRIVER_INTERRUPT
        #define PS2_CLOCK_PIN B8
        #define PS2_DATA_PIN  B9
      #endif

      其中會依 rules.mk 設定的運作模式決定引入相關定義。把接腳都設成一樣的 PIN,改變運作棤式,不需要改接線。

      stm32test.h 如下。
      #pragma once
      
      #include "quantum.h"
      
      #define LAYOUT( \
        K00, K01, K02  \
      ) { \
        { K00, K01, K02} \
      }
      stm32test.c 只有一行,如
      #include "stm32test.h"

      編譯

      執行下面的指令開始編譯
      qmk compile -kb ajtest/stm32test -km default"
      很不幸出現下面的錯誤。
      ......
      platforms/chibios/drivers/ps2/ps2_io.c: In function 'clock_lo':
      ./keyboards/ajtest/stm32test/config.h:13:27: error: 'B8' undeclared (first use in this function)
         13 |   #define PS2_CLOCK_PIN   B8
            |                           ^~
      ...........
      platforms/chibios/drivers/ps2/ps2_io.c: In function 'data_lo':
      ./keyboards/ajtest/stm32test/config.h:14:27: error: 'B9' undeclared (first use in this function)
         14 |   #define PS2_DATA_PIN    B9
            |                           ^~
      Google 找到答案,platforms/chibios/drivers/ps2/ps2_io.c 要加入一行 include,如下
      #include <stdbool.h>
      #include "ps2_io.h"
      #include "gpio.h"
      
      // chibiOS headers
      #include "ch.h"
      #include "hal.h"
      可以成功 compile,但在 link 時出錯
      Linking: .build/ajtest_stm32test_default.elf                                                        [ERRORS]
       | 
       | /usr/lib/gcc/arm-none-eabi/10.3.1/../../../arm-none-eabi/bin/ld: .build/obj_ajtest_stm32test_default/ps2_mouse.o: in function `ps2_mouse_task':
       | /home/ajax/qmk_firmware/drivers/ps2/ps2_mouse.c:93: undefined reference to `pbuf_has_data'
       | collect2: error: ld returned 1 exit status
       | 
      gmake[1]: *** [builddefs/common_rules.mk:267: .build/ajtest_stm32test_default.elf] Error 1
      gmake: *** [Makefile:392: ajtest/stm32test:default] Error 1

      在這裡卡了好久,搜尋程式碼,`pbuf_has_data' 只有定義在 drivers/ps2/ps2_interrupt.c 中,而 ps2_busywait.c 中沒有這一個 function

      後來看到 ps2_mouse.c 中呼叫 `pbuf_has_data' 的前面,有作判斷 

      "#ifdef PS2_MOUSE_USE_REMOTE_MODE"

      意思是使用 remote moe 就不會呼叫此 function。否則使用 stream mode,此模式最好使用 interrupt 運作方式。

      在 config.h 加入 "#define PS2_MOUSE_USE_REMOTE_MODE" 後,成功產生 bin 檔。

      燒錄

      使用 docker 環境,需使用 usb 裝置及 privileged 參數。執行指令如下

      docker run -it --privileged \
          -v /dev/bus/usb:/dev/bus/usb \
          -v `pwd`:/work  \
          qmk-dev bash

      可將開發板的 boot0 接到 1,連上電腦,使用 dfu-util 列出裝置。

      -----------------------------------
      # dfu-util --list
      dfu-util 0.11

      Found DFU: [1eaf:0003] ver=0201, devnum=8, cfg=1, intf=0, path="1-8.1.1", alt=2, name="STM32duino bootloader v1.0  Upload to Flash 0x8002000", serial="LLM 003"
      Found DFU: [1eaf:0003] ver=0201, devnum=8, cfg=1, intf=0, path="1-8.1.1", alt=1, name="STM32duino bootloader v1.0  Upload to Flash 0x8005000", serial="LLM 003"
      Found DFU: [1eaf:0003] ver=0201, devnum=8, cfg=1, intf=0, path="1-8.1.1", alt=0, name="STM32duino bootloader v1.0  ERROR. Upload to RAM not supported.", serial="LLM 003"
      -----------------------------------

      使用下列指令燒入 bin 檔

      ------------------------------------------
      # dfu-util -D ajtest_stm32test_default.bin -a 2
      dfu-util 0.11

      dfu-util: Warning: Invalid DFU suffix signature
      dfu-util: A valid DFU suffix will be required in a future dfu-util release
      Opening DFU capable USB device...
      Device ID 1eaf:0003
      Device DFU version 0110
      Claiming USB DFU Interface...
      Setting Alternate Interface #2 ...
      Determining device status...
      DFU state(2) = dfuIDLE, status(0) = No error condition is present
      DFU mode device DFU version 0110
      Device returned transfer size 1024
      Copying data from PC to DFU device
      Download [=========================] 100%        23248 bytes
      Download done.
      DFU state(8) = dfuMANIFEST-WAIT-RESET, status(0) = No error condition is present
      Resetting USB to switch back to runtime mode
      Done!
      ------------------------------------------

      再把 boot0 跳線回 0,重新接上電腦,使用 dmesg 看到下列訊息

      -------------------------------------------------
      [  813.021552] usb 1-8.1.1: new full-speed USB device number 11 using xhci_hcd
      [  813.113109] usb 1-8.1.1: New USB device found, idVendor=1234, idProduct=5678, bcdDevice= 0.01
      [  813.113123] usb 1-8.1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
      [  813.113130] usb 1-8.1.1: Product: Trackpoint Demo
      [  813.113135] usb 1-8.1.1: Manufacturer: QMK
      [  813.121950] input: QMK Trackpoint Demo as /devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.1/1-8.1.1/1-8.1.1:1.0/0003:1234:5678.000C/input/input33
      [  813.178954] hid-generic 0003:1234:5678.000C: input,hidraw0: USB HID v1.11 Keyboard [QMK Trackpoint Demo] on usb-0000:00:14.0-8.1.1/input0
      [  813.180015] input: QMK Trackpoint Demo as /devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.1/1-8.1.1/1-8.1.1:1.1/0003:1234:5678.000D/input/input34
      [  813.180655] hid-generic 0003:1234:5678.000D: input,hidraw1: USB HID v1.11 Mouse [QMK Trackpoint Demo] on usb-0000:00:14.0-8.1.1/input1
      [  813.182002] input: QMK Trackpoint Demo System Control as /devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.1/1-8.1.1/1-8.1.1:1.2/0003:1234:5678.000E/input/input35
      [  813.238550] input: QMK Trackpoint Demo Consumer Control as /devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.1/1-8.1.1/1-8.1.1:1.2/0003:1234:5678.000E/input/input36
      [  813.238850] input: QMK Trackpoint Demo Keyboard as /devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.1/1-8.1.1/1-8.1.1:1.2/0003:1234:5678.000E/input/input37
      [  813.239723] hid-generic 0003:1234:5678.000E: input,hidraw2: USB HID v1.11 Keyboard [QMK Trackpoint Demo] on usb-0000:00:14.0-8.1.1/input2
      -------------------------------------------------

      使用鍵盤測試程式,測試鍵盤功能正確。

      測試 interrupt 運作模式

      接下來測試 interrupt 的運作模式。QMK 中,對於 stm32 並沒有支援 best 的 USART 運作模式,只能退而求其,使用 better 的 interrupt 運作模式

      按照 QMK 的說明,除了設定 rules.mk 和 config.h 的設定值外,還要修改 

      platforms/chibios/boards/common/configs/halconf.h

      加入 "#define PAL_USE_CALLBACKS   TRUE",為了確保有一定會加上,我是把原來設定為 FALSE 的設定註解掉,把新的設定放在判斷區塊之外。

      修改後,執行編譯再次出現錯誤誤。

      ......
      drivers/ps2/ps2_interrupt.c: In function 'ps2_host_init':
      ./keyboards/ajtest/stm32test/config.h:20:25: error: 'B8' undeclared (first use in this function)
         13 |   #define PS2_CLOCK_PIN   B8
            |                           ^~
      ...........
      drivers/ps2/ps2_interrupt.c: In function 'ps2_host_send':
      ./keyboards/ajtest/stm32test/config.h:20:25: error: 'B8' undeclared (first use in this function)
         14 |   #define PS2_DATA_PIN    B8
            |                           ^~
      在 drivers/ps2/ps2_interrupt.c 加上 include 即可,如下
      #if defined(__AVR__)
      #    include <avr/interrupt.h>
      #elif defined(PROTOCOL_CHIBIOS) // TODO: or STM32 ?
      // chibiOS headers
        #include "gpio.h"
      #    include "ch.h"
      #    include "hal.h"
      #endif                           ^~
      編譯成功。燒錄至開發板,測試功能正常。接下來就可以改裝有小紅點功能的鍵盤了。



      網誌存檔