本帖最后由 jf_1137202360 于 2022-11-17 09:50 编辑
前言 从现在开始我们一步一步来移植NES游戏模拟器,制作一个掌上游戏机。移植NES游戏模拟器主要需要实现按键输入,显示,音频输出三个部分。今天实现第一个部分按键输入。
USB输入设备
USB输入设备连接连接USB手柄之前查看输入设备
root@forlinx:/# ls /dev/input/
by-path event0 event1 event2 event3 event4 event5 event6 event7
连接USB手柄到USB,串口打印如下信息
root@forlinx:/# [ 226.010337] sunxi-ehci 5200000.ehci1-controller: ehci_irq: highspeed device connect
[ 226.124208] sunxi-ehci 5200000.ehci1-controller: ehci_irq: highspeed device disconnect
[ 226.447414] usb 4-1: new low-speed USB device number 2 using sunxi-ohci
[ 226.626351] input: USB Gamepad as /devices/platform/soc/5200000.ohci1-controller/usb4/4-1/4-1:1.0/0003:0810:0001.0001/input/input8
[ 226.641073] pantherlord 0003:0810:0001.0001: input,hidraw0: USB HID v1.10 Joystick [ USB Gamepad ] on usb-sunxi-ohci-1/input0
[ 226.654664] pantherlord 0003:0810:0001.0001: Force feedback for PantherLord/GreenAsia devices by Anssi Hannula <anssi.hannula@gmail.com>
查看输入设备多了event8
root@forlinx:/# ls /dev/input/
by-id event0 event2 event4 event6 event8
by-path event1 event3 event5 event7
cat /proc/bus/input/devices查看设备信息
I: Bus=0003 Vendor=0810 Product=0001 Version=0110
N: Name=" USB Gamepad "
P: Phys=usb-sunxi-ohci-1/input0
S: Sysfs=/devices/platform/soc/5200000.ohci1-controller/usb4/4-1/4-1:1.0/0003:0810:0001.0001/input/input8
U: Uniq=
H: Handlers=event8
B: PROP=0
B: EV=20001b
B: KEY=fff00000000 0 0 0 0
B: ABS=30027
B: MSC=10
B: FF=107030000 0
输入设备测试
测试方法1evtest
root@forlinx:/# evtest
No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0: sunxi-keyboard
/dev/input/event1: goodix-gt911
/dev/input/event2: axp2101-pek
/dev/input/event3: sunxi-gpadc0
/dev/input/event4: sunxi-gpadc1
/dev/input/event5: sunxi-gpadc2
/dev/input/event6: sunxi-gpadc3
/dev/input/event7: sunxi-ir
/dev/input/event8: USB Gamepad
Select the device event number [0-8]:
然后输入对应的数字8 会同步报告状态
Event: time 1641792216.413657, -------------- SYN_REPORT ------------
Event: time 1641792216.421656, type 3 (EV_ABS), code 16 (ABS_HAT0X), value 0
Event: time 1641792216.421656, type 3 (EV_ABS), code 17 (ABS_HAT0Y), value 0
Event: time 1641792216.421656, -------------- SYN_REPORT ------------
Event: time 1641792216.429657, type 3 (EV_ABS), code 16 (ABS_HAT0X), value 0
Event: time 1641792216.429657, type 3 (EV_ABS), code 17 (ABS_HAT0Y), value 0
Event: time 1641792216.429657, -------------- SYN_REPORT ------------
Event: time 1641792216.437656, type 3 (EV_ABS), code 16 (ABS_HAT0X), value 0
Event: time 1641792216.437656, type 3 (EV_ABS), code 17 (ABS_HAT0Y), value 0
Event: time 1641792216.437656, -------------- SYN_REPORT ------------
Event: time 1641792216.445658, type 3 (EV_ABS), code 16 (ABS_HAT0X), value 0
Event: time 1641792216.445658, type 3 (EV_ABS), code 17 (ABS_HAT0Y), value 0
Event: time 1641792216.445658, -------------- SYN_REPORT ------------
Event: time 1641792216.453657, type 3 (EV_ABS), code 16 (ABS_HAT0X), value 0
Event: time 1641792216.453657, type 3 (EV_ABS), code 17 (ABS_HAT0Y), value 0
Event: time 1641792216.453657, -------------- SYN_REPORT ------------
Event: time 1641792216.461657, type 3 (EV_ABS), code 16 (ABS_HAT0X), value 0
Event: time 1641792216.461657, type 3 (EV_ABS), code 17 (ABS_HAT0Y), value 0
按SELECT按键则会打印如下信息
Event: time 1641792272.781665, type 4 (EV_MSC), code 4 (MSC_SCAN), value 90009
Event: time 1641792272.781665, type 1 (EV_KEY), code 296 (BTN_BASE3), value 0
测试方法2或者直接cat /dev/input/event8 | hexdump -C查看 打印如下
0000b0c0 b0 fa 0e 00 00 00 00 00 03 00 11 00 00 00 00 00 |................|
0000b0d0 c5 c3 db 61 00 00 00 00 b0 fa 0e 00 00 00 00 00 |...a............|
0000b0e0 00 00 00 00 00 00 00 00 c5 c3 db 61 00 00 00 00 |...........a....|
0000b0f0 f0 19 0f 00 00 00 00 00 03 00 10 00 00 00 00 00 |................|
0000b100 c5 c3 db 61 00 00 00 00 f0 19 0f 00 00 00 00 00 |...a............|
0000b110 03 00 11 00 00 00 00 00 c5 c3 db 61 00 00 00 00 |...........a....|
0000b120 f0 19 0f 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
0000b130 c5 c3 db 61 00 00 00 00 5c 39 0f 00 00 00 00 00 |...a....9......|
0000b140 03 00 10 00 00 00 00 00 c5 c3 db 61 00 00 00 00 |...........a....|
0000b150 5c 39 0f 00 00 00 00 00 03 00 11 00 00 00 00 00 |9..............|
按键也会有相应的变化
按键输入设备
按键输入设备
从设备名字可以看出event0对应按键
/dev/input/event0: sunxi-keyboard
cat /proc/bus/input/devices也可以看出
I: Bus=0019 Vendor=0001 Product=0001 Version=0100
N: Name="sunxi-keyboard"
P: Phys=sunxikbd/input0
S: Sysfs=/devices/virtual/input/input0
U: Uniq=
H: Handlers=event0
B: PROP=0
B: EV=3
B: KEY=100000000800 c000000000000 10000000
按键测试
测试方法1evtest
No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0: sunxi-keyboard
/dev/input/event1: goodix-gt911
/dev/input/event2: axp2101-pek
/dev/input/event3: sunxi-gpadc0
/dev/input/event4: sunxi-gpadc1
/dev/input/event5: sunxi-gpadc2
/dev/input/event6: sunxi-gpadc3
/dev/input/event7: sunxi-ir
/dev/input/event8: USB Gamepad
Select the device event number [0-8]:
输入0
Select the device event number [0-8]: 0
Input driver version is 1.0.1
Input device ID: bus 0x19 vendor 0x1 product 0x1 version 0x100
Input device name: "sunxi-keyboard"
Supported events:
Event type 0 (EV_SYN)
Event type 1 (EV_KEY)
Event code 28 (KEY_ENTER)
Event code 114 (KEY_VOLUMEDOWN)
Event code 115 (KEY_VOLUMEUP)
Event code 139 (KEY_MENU)
Event code 172 (KEY_HOMEPAGE)
Properties:
Testing ... (interrupt to exit)
按键VOL+
Event: time 1641793128.298100, type 1 (EV_KEY), code 115 (KEY_VOLUMEUP), value 1
Event: time 1641793128.298100, -------------- SYN_REPORT ------------
Event: time 1641793128.423096, type 1 (EV_KEY), code 115 (KEY_VOLUMEUP), value 0
Event: time 1641793128.423096, -------------- SYN_REPORT ------------
按键VOL-
Event: time 1641793129.298135, type 1 (EV_KEY), code 114 (KEY_VOLUMEDOWN), value 1
Event: time 1641793129.298135, -------------- SYN_REPORT ------------
Event: time 1641793129.438758, type 1 (EV_KEY), code 114 (KEY_VOLUMEDOWN), value 0
Event: time 1641793129.438758, -------------- SYN_REPORT ------------
按键MENU
Event: time 1641793130.173129, type 1 (EV_KEY), code 139 (KEY_MENU), value 1
Event: time 1641793130.173129, -------------- SYN_REPORT ------------
Event: time 1641793130.298126, type 1 (EV_KEY), code 139 (KEY_MENU), value 0
Event: time 1641793130.298126, -------------- SYN_REPORT ------------
按键ENTER
Event: time 1641793131.344952, type 1 (EV_KEY), code 28 (KEY_ENTER), value 1
Event: time 1641793131.344952, -------------- SYN_REPORT ------------
Event: time 1641793131.423119, type 1 (EV_KEY), code 28 (KEY_ENTER), value 0
Event: time 1641793131.423119, -------------- SYN_REPORT ------------
按键HOME
Event: time 1641793132.891816, type 1 (EV_KEY), code 172 (KEY_HOMEPAGE), value 1
Event: time 1641793132.891816, -------------- SYN_REPORT ------------
Event: time 1641793132.985563, type 1 (EV_KEY), code 172 (KEY_HOMEPAGE), value 0
Event: time 1641793132.985563, -------------- SYN_REPORT ------------
测试方法2root@forlinx:/# cat /dev/input/event0 | hexdump -C 按键VOL+
00000000 cf c4 db 61 00 00 00 00 2a 5a 04 00 00 00 00 00 |...a....*Z......|
00000010 01 00 73 00 01 00 00 00 cf c4 db 61 00 00 00 00 |..s........a....|
00000020 2a 5a 04 00 00 00 00 00 00 00 00 00 00 00 00 00 |*Z..............|
00000030 cf c4 db 61 00 00 00 00 70 42 06 00 00 00 00 00 |...a....pB......|
00000040 01 00 73 00 00 00 00 00 cf c4 db 61 00 00 00 00 |..s........a....|
00000050 70 42 06 00 00 00 00 00 00 00 00 00 00 00 00 00 |pB..............|
按键VOL-
00000060 d3 c4 db 61 00 00 00 00 a5 ae 02 00 00 00 00 00 |...a............|
00000070 01 00 72 00 01 00 00 00 d3 c4 db 61 00 00 00 00 |..r........a....|
00000080 a5 ae 02 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000090 d3 c4 db 61 00 00 00 00 fc 10 05 00 00 00 00 00 |...a............|
000000a0 01 00 72 00 00 00 00 00 d3 c4 db 61 00 00 00 00 |..r........a....|
000000b0 fc 10 05 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
按键MENU
000000c0 d5 c4 db 61 00 00 00 00 02 8b 05 00 00 00 00 00 |...a............|
000000d0 01 00 8b 00 01 00 00 00 d5 c4 db 61 00 00 00 00 |...........a....|
000000e0 02 8b 05 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000f0 d5 c4 db 61 00 00 00 00 25 7f 06 00 00 00 00 00 |...a....%.......|
00000100 01 00 8b 00 00 00 00 00 d5 c4 db 61 00 00 00 00 |...........a....|
00000110 25 7f 06 00 00 00 00 00 00 00 00 00 00 00 00 00 |%...............|
按键ENTER
00000120 d7 c4 db 61 00 00 00 00 91 eb 02 00 00 00 00 00 |...a............|
00000130 01 00 1c 00 01 00 00 00 d7 c4 db 61 00 00 00 00 |...........a....|
00000140 91 eb 02 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000150 d7 c4 db 61 00 00 00 00 aa a2 03 00 00 00 00 00 |...a............|
00000160 01 00 1c 00 00 00 00 00 d7 c4 db 61 00 00 00 00 |...........a....|
00000170 aa a2 03 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
按键HOME
00000180 da c4 db 61 00 00 00 00 1c 4c 00 00 00 00 00 00 |...a.....L......|
00000190 01 00 ac 00 01 00 00 00 da c4 db 61 00 00 00 00 |...........a....|
000001a0 1c 4c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |.L..............|
000001b0 da c4 db 61 00 00 00 00 34 03 01 00 00 00 00 00 |...a....4.......|
000001c0 01 00 ac 00 00 00 00 00 da c4 db 61 00 00 00 00 |...........a....|
000001d0 34 03 01 00 00 00 00 00 00 00 00 00 00 00 00 00 |4...............|
输入设备代码操作
由于游戏需要至少A,B,SELECT,START,UP,DOWN,LEFT,RIGHT 8个按键, 所以板载按键只有5个可用,所以只能使用USB游戏手柄,刚好手里有一个USB手柄,我们就以该手柄进行测试。
需要实现以下获取按键的函数
/* Query a button's state.
Returns 1 if button #b is pressed. */
int nes_key_state(int b)
{
ALLEGRO_KEYBOARD_STATE state;
al_get_keyboard_state(&state);
switch (b)
{
case 0: // On / Off
return 1;
case 1: // A
return al_key_down(&state, ALLEGRO_KEY_K);
case 2: // B
return al_key_down(&state, ALLEGRO_KEY_J);
case 3: // SELECT
return al_key_down(&state, ALLEGRO_KEY_U);
case 4: // START
return al_key_down(&state, ALLEGRO_KEY_I);
case 5: // UP
return al_key_down(&state, ALLEGRO_KEY_W);
case 6: // DOWN
return al_key_down(&state, ALLEGRO_KEY_S);
case 7: // LEFT
return al_key_down(&state, ALLEGRO_KEY_A);
case 8: // RIGHT
return al_key_down(&state, ALLEGRO_KEY_D);
default:
return 1;
}
}
先编写按键测试代码如下 struct input_event参见input.h的定义
`#include`
`#include`
`#include`
`#include`
`#include`
`#include`
`#include`
`#include `
`#include `
`#include `
`#include `
int s_keys_fd = -1;
uint32_t s_keys_state = 0;
void* key_poll(void* arg)
{
char ret[2];
struct input_event t;
s_keys_fd = open((char*)arg, O_RDONLY);
if(s_keys_fd <= 0)
{
printf("open %s device error!n",(char*)arg);
return 0;
}
while(1)
{
if(read(s_keys_fd, &t, sizeof(t)) == sizeof(t))
{
if(t.type==EV_KEY)
{
if(t.value==0 || t.value==1)
{
printf("key %d %sn", t.code, (t.value) ? "Pressed" : "Released");
//if(t.code == KEY_ESC)
// break;
}
}
else
{
///printf("type %d code %d value %dn", t.type, t.code, t.value);
}
}
}
return 0;
}
void key_init(void* arg)
{
pthread_t id;
/* 创建函数线程,并且指定函数线程要执行的函数 */
int res = pthread_create(&id,NULL,key_poll,arg);
assert(res == 0);
while(1)
{
}
exit(0);
}
int key_getstate(int key)
{
}
int main(int argc, char* argv[])
{
key_init(argv[1]);
while(1);
}
编译 aarch64-linux-gnu-gcc key.c -o key -lpthread
chmod +x key
运行./key /dev/input/event8
测试
按键SELECT key 296 Pressed key 296 Released
按键START key 297 Pressed key 297 Released
右边按键上 key 288 Pressed key 288 Released
右边按键下 key 290 Pressed key 290 Released
右边按键左 key 291 Pressed key 291 Released
右边按键右 key 289 Pressed key 289 Released
右边 前面 上按键 key 293 Pressed key 293 Released
右边 前面 下按键 key 295 Pressed key 295 Released
左边 前面 上按键 key 292Pressed key 292 Released
左边 前面 下按键 key 294 Pressed key 294 Released
左边的上下左右四个按键无响应。
总结 我们现在实现了游戏手柄按键输入的采集,完成了第一部分,后面继续显示和音频部分。
0
|
|
|
|