当前位置:网站首页>How to convert an old keyboard into a USB keyboard and program it yourself?
How to convert an old keyboard into a USB keyboard and program it yourself?
2022-06-27 00:52:00 【arenascat】
What is? PS/2 Interface
PS/2 yes IBM For PC The interface of , The connectors share 6 Holes , Circular design , stay 1990~2000 The desktop keyboard around time is PS/2 Interface , Although in 1996 Years have come USB Interface , But it is limited by the chip cost and design scheme , At that time, many mechanical keyboards still used PS/2 Interface .
Because the protocol and descriptor are not recognized , So the keyboard and mouse must be plugged into a specific interface divided by color to work .
PS/2 Interface and current USB Interfaces have many commonalities , For example, the number of cables actually used is 4 root ,5V Power supply , But there are differences in the form of transmission ,PS/2 The interface is a clock line and a data line , and USB Data transmission is D- D+ Differential line .
and USB Comparison ,PS/2 Low difficulty in interface data processing , Low frequency , Compatibility is good. , After pressing the key , The keyboard will be pulled down CLK level , transmission 12bit Of DATA The signal , Pulling down this action will cause an interrupt signal to trigger interrupt processing in the motherboard chipset , So theoretically, the reaction will be better than USB faster .
How to program and decode by yourself
PS/2 Interface data reading is relatively simple , But there are still some difficulties in programming ,PS/2 The interface transmits 11bit data , The first 12Bit It must be 0. The difficulty here mainly lies in the key discrimination and passing USB On transmission .
Modules can be selected Arduino Leonardo, There is a good balance between cost and programming difficulty , Most of the time I prefer to use low code ( Code that can implement complex functions simply by calling ) To create and modify .
Use modules and special chips to convert into USB
It should be internally modified to USB, The first choice is the chip that can be used , I bought some WIT122UH For testing , Its price is only a few dollars .
In my design, I consider that most of the time it is used for built-in , So this module is only configured with the minimum components .
Then I designed a more complicated , I used a purple one PS/2 Female seat , Models for DS1093-01-PN60
There is also an enhanced design that adds 16Pin Of Type-C Interface , There is also a mother seat , If you want to start from the difficulty of welding , You can put Type-C Replace interface with 4pin Of Micro-USB Interface .
Module design , Consider two possibilities , One is external design and the other is built-in design
If you want to simplify DIY Processes can directly use these common PS/2 Interface to USB, Taking them apart can compress the volume very well .
The lines
because PS/2 The signal is easy to simulate , It's easy to use 8Bit Of MCU Generate , therefore , If you make a keyboard , So use PS/2 turn USB Signal chip , You can use native in a relative way USB The interface chip can be made at a much lower cost USB Interface keyboard .
To solve by programming
I use Leonardo and Arduino IDE To do this , Have a lot of freedom , The application library is PS2KeyAdvanced https://github.com/techpaul/PS2KeyAdvanced
The corresponding keyboard is a Cherry G84-4400,PS2 Interface
I use PS2KeyAdvanced library , And another one. PS2Keyboard The library is comparatively , This library can support lighting CAPS LOCK The lamp , This light requires the controller to support data writing . That is to write data to the keyboard .
Line connection , I put DATA Connected to the D2,CLK Connected to the D3.
Description of various functions
keyboard.available() The function is simple , It is triggered when data is obtained and returned at other times 0, So in loop To constantly determine whether there is a return value 1. Of course, in fact, the data has been buffered , Because the interrupt was set at the beginning , Interrupt function to process the data sent by the keyboard .
Key value query
//sample With A For example : Press code Release code
// commonly : 41 8041
//CAPS LOCK Next : 1041 9041
//SHIFT Press and hold : 4041 C041
//SHIFT Key :4106 8106
Complete code
#include "Keyboard.h"
#include <PS2KeyAdvanced.h>
// Abreast of the times , be used for PS2 The switch to USB
//sample With A For example : Press code Release code
// commonly : 41 8041
//CAPS LOCK Next : 1041 9041
//SHIFT Press and hold : 4041 C041
//SHIFT Key :4106 8106
/* Keyboard constants Change to suit your Arduino
define pins used for data and clock from keyboard */
#define DATAPIN 2
#define IRQPIN 3
#define UPPER 40
#define RELEASE_UPPER C0
#define SHIFTMODE 0x40
#define FUNCTION 0x80
uint16_t c;
PS2KeyAdvanced keyboard;
void setup( )
{
// Configure the keyboard library
keyboard.begin( DATAPIN, IRQPIN );
Serial.begin( 115200 );
Serial.println( "PS2 Advanced Key Simple Test:" );
Keyboard.begin();
}
void loop( )
{
if ( keyboard.available( ) )
{
// read the next key
c = keyboard.read( );
//For DEBUG
if ( c > 0 )
{
// DisValue(c);//DEBUG With , obtain c The specific value of , Status symbols and key values
}
//ACTION
if ((c & 0xFF) > 0) // Judge the obtained key value c Is there anything greater than 0
{
DisValue(c);
switch (c >> 8)
{
case 0x10:// Press the letter under caps lock
UpperKey(c);
break;
case 0x90:// Release letters under caps lock
UpperKey_Release(c);
break;
case 0x40://SHIFT Press... In uppercase
UpperKey(c);
break;
case 0xC0://SHIFT Capitalize release
UpperKey_Release(c);
break;
case 0x11:
if (c == 0x111D)
{
Keyboard.press(KEY_TAB);
}
break;
case 0x91:
if (c == 0x911D)
{
Keyboard.release(KEY_TAB);
}
break;
case 0x00:// Generally press the key
standardKey(c);
case 0x80:// General key release
standardKey_Release(c);
break;
case 0x01:// Function buttons
FuncKey(c);
break;
case 0x81:// Function keys and SHIFT Key release
Serial.println( "FUNC RELEASE" );
FuncKey_Release(c);
break;
case 0x41://SHIFT Key pressed
break;
break;
case 0x20://CTRL Press And
Keyboard.press(KEY_LEFT_CTRL);
standardKey(c);
break;
case 0xA0://CTRL Release
Keyboard.release(KEY_LEFT_CTRL);
standardKey_Release(c);
break;
case 0x21: //CTRL
Serial.println( "CTRL PRESS" );
Keyboard.press(KEY_LEFT_CTRL);
break;
case 0x9: //LEFT-ALT
Serial.println( "L-ALT PRESS" );
Keyboard.press(KEY_LEFT_ALT);
break;
case 0x5: //RIGHT-ALT
Serial.println( "R-ALT PRESS" );
Keyboard.press(KEY_RIGHT_ALT);
break;
default:
Serial.print( " Unknow Higher code: " );
Serial.println( c >> 8, HEX );
}
// Keyboard.press(c);
}
}
}
///
/*
Descript: For DEBUG
*///
void DisValue(unsigned int c)
{
Serial.print( "Value " );
Serial.print( c, HEX );
Serial.print( " - Status Bits " );
Serial.print( c >> 8, HEX );
Serial.print( " Code " );
Serial.println( c & 0xFF, HEX );
}
///
/*
Descript: abcde and so on,main key
*///
#define LEFT_WIN 0x008B//press
#define CAPELOCK 0x00FA//press
void standardKey(unsigned int c)
{
int key = c << 8;
Serial.print("Stand press :");
if(remap(c)!=0)
{
Keyboard.press(remap(c));
return;
}
if (((key >> 8) >= '@') && ((key >> 8) <= 'Z'))
{
Serial.write((key >> 8) + (97 - 65)); // Output lowercase characters
Keyboard.press(c + ' ');
}
else
{
Serial.write((key >> 8)); // Output other characters
Keyboard.press(c);
}
Serial.println("");
}
//return 0: not found
unsigned char remap(unsigned int c)
{
unsigned int key = c << 8;
unsigned char remap_char=0;
switch (key>>8)
{
case 0x3E:
remap_char = '/';
break;
case 0x3B:
remap_char = ',';
break;
case 0x3A: // Key [']
remap_char = 0x27;
break;
case 0x8B:
remap_char = KEY_LEFT_GUI;
break;
case 0x3D:
remap_char = '.';
break;
case 0xFA:
remap_char = KEY_CAPS_LOCK;
break;
default:
break;
}
return remap_char;
}
//CODE:0x 80??
void standardKey_Release(unsigned int c)
{
int key = c << 8;
Serial.print("Stand Release :");
if(remap(c)!=0)
{
Keyboard.release(remap(c));
return;
}
if (((key >> 8) >= 'A') && ((key >> 8) <= 'Z'))
{
Serial.write((key >> 8) + (97 - 65)); // Output lowercase characters
Keyboard.release(c + ' ');
}
else
{
Serial.write((key >> 8)); // Output other characters
Keyboard.release(c);
}
Serial.println("");
}
void UpperKey(unsigned int c)
{
int key = c << 8;
unsigned int chara;
Serial.print("Upper press :");
if (c == 0x403A) //["]
{
Keyboard.press(0x22);
return;
}
if ((key >> 8) >= '0' && (key >> 8) <= '9')
{
switch (key >> 8)
{
case '0':
chara = ')';
break;
case '1':
chara = '!';
break;
case '2':
chara = '@';
break;
case '3':
chara = '#';
break;
case '4':
chara = '$';
break;
case '5':
chara = '%';
break;
case '6':
chara = '^';
break;
case '7':
chara = '&';
break;
case '8':
chara = '*';
break;
case '9':
chara = '(';
break;
default:
break;
}
Serial.write(chara);
Serial.println("");
Keyboard.press(chara);
}
else
{
Serial.write(key >> 8);
Serial.println("");
Keyboard.press(key >> 8);
}
}
void UpperKey_Release(unsigned int c)
{
int key = c << 8;
Serial.print("Upper release :");
Serial.write(key >> 8);
if (c == 0xC03A) //["]
{
Keyboard.release(0x22);
return;
}
Serial.println("");
Keyboard.releaseAll();
}
void rep(String s)
{
Serial.print("Func press:");
Serial.println(s);
}
void FuncKey(unsigned int c)
{
int key = c << 8;
switch (key >> 8)
{case 0x1B :
rep("ESC");
Keyboard.press(KEY_ESC);
break;
case PS2_KEY_ENTER :
rep("ENTER");
Keyboard.press(0x28);
break;
case PS2_KEY_SPACE:
rep("SPACE");
Keyboard.press(0x20);
break;
case PS2_KEY_TAB :
rep("TAB");
Keyboard.press(KEY_TAB);
break;
case PS2_KEY_DELETE :
rep("DELETE");
Keyboard.press(KEY_DELETE);
break;
case PS2_KEY_INSERT :
Keyboard.press(KEY_INSERT);
rep("INSERT");
break;
case PS2_KEY_UP_ARROW :
rep("UP");
Keyboard.press(KEY_UP_ARROW);
break;
case PS2_KEY_DN_ARROW :
Keyboard.press(KEY_DOWN_ARROW );
rep("DOWN");
break;
case PS2_KEY_L_ARROW :
Keyboard.press(KEY_LEFT_ARROW );
rep("L_ARROW");
break;
case PS2_KEY_R_ARROW :
Keyboard.press(KEY_RIGHT_ARROW);
rep("R_ARROW");
break;
case PS2_KEY_PGDN :
Keyboard.press(KEY_PAGE_DOWN );
rep("PGDN");
break;
case PS2_KEY_PGUP :
Keyboard.press(KEY_PAGE_UP );
rep("PGUP");
break;
case PS2_KEY_END :
Keyboard.press(KEY_END );
rep("END");
break;
case PS2_KEY_HOME:
Keyboard.press(KEY_HOME );
rep("HOME");
break;
case PS2_KEY_SYSRQ :
Keyboard.press(PS2_KEY_SYSRQ);
rep("SYSRQ");
break;
case PS2_KEY_BACK:
Keyboard.press(PS2_KEY_BACK);
rep("BACK");
break;
case 0x04:
rep("PRINT SCREEN");
break;
case PS2_KEY_F1 :
rep("F1");
Keyboard.press(KEY_F1);
break;
case PS2_KEY_F2 :
rep("F2");
Keyboard.press(KEY_F2);
break;
case PS2_KEY_F3 :
rep("F3");
Keyboard.press(KEY_F3);
break;
case PS2_KEY_F4 :
rep("F4");
Keyboard.press(KEY_F4);
break;
case PS2_KEY_F5 :
rep("F5");
Keyboard.press(KEY_F5);
break;
case PS2_KEY_F6 :
rep("F6");
Keyboard.press(KEY_F6);
break;
case PS2_KEY_F7 :
rep("F7");
Keyboard.press(KEY_F7);
break;
case PS2_KEY_F8 :
rep("F8");
Keyboard.press(KEY_F8);
break;
case PS2_KEY_F9 :
rep("F9");
Keyboard.press(KEY_F9);
break;
case PS2_KEY_F10 :
rep("F10");
Keyboard.press(KEY_F10);
break;
case PS2_KEY_F11 :
rep("F11");
Keyboard.press(KEY_F11);
break;
case PS2_KEY_F12 :
rep("F12");
Keyboard.press(KEY_F12);
break;
case PS2_KEY_F13 :
rep("F13");
break;
case 0x1C:
Keyboard.press(KEY_BACKSPACE);
break;
default:
Serial.print("UNKNOW CODE:");
Serial.println(c, HEX);
}
}
void FuncKey_Release(unsigned int c)
{
// Keyboard.release(c);
Keyboard.releaseAll();
}
void KeyBoard_Press(unsigned int c)
{
Keyboard.press(c);
}
void KeyBoard_Release(unsigned int c)
{
Keyboard.release(c);
}
边栏推荐
- 寻找旋转排序数组中的最小值 II[经典抽象二分 + 如何破局左中右三者相等]
- 气液滑环与其他滑环的工作原理有什么区别
- Kubeadm create kubernetes cluster
- 小白看MySQL--windows环境安装MySQL
- Competition Registration | one of the key ai+ scientific computing competitions - China open source scientific software creativity competition, competing for 100000 bonus!
- kubernetes可视化界面dashboard
- About Random Numbers
- 05 | 规范设计(下):commit 信息风格迥异、难以阅读,如何规范?
- 解决STC8G1K08程序不能运行的问题和端口配置
- Serial port debugging tool mobaxtermdownload
猜你喜欢
【Mysql】时间字段默认设置为当前时间
剑指 Offer 10- II. 青蛙跳台阶问题
BootstrapBlazor + FreeSql实战 Chart 图表使用(2)
Flink practical problems (VII): no watermark (watermarks are only available eventtime is used)
光谱共焦如何测量玻璃基板厚度
【Vscode】预览md文件
解决u8glib只显示一行文字或者不显示的问题
05 | 规范设计(下):commit 信息风格迥异、难以阅读,如何规范?
Oracle 数据库基本知识概念
[vscade] preview MD file
随机推荐
Com. Faster XML. Jackson. DataBind. Exc.mismatchedinputexception: tableau ou chaîne attendu. At [Source: X
Using physical information neural network to solve hydrodynamics equations
Concepts de base de données Oracle
这3个并发编程的核心,竟然还有人不知道?
小白看MySQL--windows环境安装MySQL
基于SSMP的宠物医院管理系统
Competition Registration | one of the key ai+ scientific computing competitions - China open source scientific software creativity competition, competing for 100000 bonus!
1+1<2 ?! Interpretation of hesic papers
Technical dry goods | top speed, top intelligence and minimalist mindspore Lite: help Huawei watch become more intelligent
指南针开户安全的吗?
Law of Large Numbers
What is the difference between the working principle of gas-liquid slip ring and other slip rings
巧记大小端字节序
C#程序结构预览最基础入门
No clue about complex data?
其他服务注册与发现
BootstrapBlazor + FreeSql实战 Chart 图表使用(2)
Xiaobai looks at MySQL -- installing MySQL in Windows Environment
Is it reliable to speculate in stocks by mobile phone? Is it safe to open an account and speculate in stocks online
Lambda expression