USB эмуляция клавиатуры или NES-USB

DSCN60656566

Отладочная плата Arduino Due построена на базе ATSAM3X, который имеет при себе собственный USB порт в периферии. Для среды разработки Arduino IDE не так давно были написаны простые инструменты для работы с портом, а в частности, работа в качестве HID устройства в системе ПК.

 

Уже третий год у меня пылится игровой контроллер от приставки NES. Существует множество проектов, которые используют Arduino и передают данные через FTDI.  Почему бы  не подключить контроллер к ПК через стандартный USB?

Ashampoo_Snap_2015.04.06_14h48m28s_002_

 

Пожалуй эту будет один из самых глупых способов использования 32-х бит ARM микроконтроллера. :-) В данном случае проще всего прикинуться USB клавиатурой и эмулировать нажатия клавиш. Из примеров с сайта разработчиков можно выделить несколько необходимых функций:

  • Keyboard.begin() — инициализация
  • Keyboard.releaseAll() — отпустить все клавиши
  • Keyboard.press(char c) — нажать клавишу
  • Keyboard.release(char c) — отпустить клавишу
  • Keyboard.print(char *c) — напечатать сообщение

Все коды клавиш можно найти здесь. К примеру, следующий код должен напечатать небольшое сообщение:

1
2
3
4
5
6
7
8
9
10
void setup() {
	Keyboard.begin();
        Keyboard.releaseAll();
        delay(1000);
        Keyboard.print("Hello!"); //Просто?
}
 
void loop() {
 
}

Загрузите программу, затем подключите плату через Native USB.

Собственно говоря, для нашего USB игрового контроллера нам необходимо опрашивать кнопки и отправлять данные о нажатиях в порт.

Дело в том, что постоянно передавать данные в порт — неправильное решение данной задачи. Необходимо отслеживать изменение состояния каждой кнопки и лишь при изменении (нажатии/отпускании) передавать данные.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <nesinterface.h>
 
#define K_RIGHT(x)  boolean((x >> 7) & 0x01)
#define K_LEFT(x)   boolean((x >> 6) & 0x01)
#define K_UP(x)     boolean((x >> 4) & 0x01)
#define K_DOWN(x)   boolean((x >> 5) & 0x01)
#define K_A(x)      boolean((x >> 1) & 0x01)
#define K_B(x)      boolean((x >> 0) & 0x01)
#define K_START(x)  boolean((x >> 3) & 0x01)
#define K_SELECT(x) boolean((x >> 2) & 0x01)
 
#define latch 6 //Пин для LATCH
#define clock 5 //Пин для CLOCK
#define data  7 //Пин для DATA
 
NES NES;
 
byte val, prev, delta;
 
void setup() {
	NES.Init(clock, latch, data); //Настройка портов NES контроллера
	Keyboard.begin();
        Keyboard.releaseAll(); //На всякий случай отпускаем все клавиши.
 
        prev = 0;
}
 
void emulate() {
        if (K_UP(delta)) 
          if (K_UP(val))
            Keyboard.press(KEY_UP_ARROW);
          else
            Keyboard.release(KEY_UP_ARROW);
 
         if (K_DOWN(delta))
          if (K_DOWN(val))
            Keyboard.press(KEY_DOWN_ARROW);
          else
            Keyboard.release(KEY_DOWN_ARROW);   
 
         if (K_RIGHT(delta))
          if (K_RIGHT(val))
            Keyboard.press(KEY_RIGHT_ARROW);
          else
            Keyboard.release(KEY_RIGHT_ARROW);
 
         if (K_LEFT(delta))
          if (K_LEFT(val))
            Keyboard.press(KEY_LEFT_ARROW);
          else
            Keyboard.release(KEY_LEFT_ARROW); 
 
         if (K_A(delta))
          if (K_A(val))
            Keyboard.press('z');
          else
            Keyboard.release('z'); 
 
         if (K_B(delta))
          if (K_B(val))
            Keyboard.press('x');
          else
            Keyboard.release('x');   
 
         if (K_START(delta))
          if (K_START(val))
            Keyboard.press('s');
          else
            Keyboard.release('s'); 
 
         if (K_SELECT(delta))
          if (K_SELECT(val))
            Keyboard.press('a');
          else
            Keyboard.release('a');             
}
 
void loop() {
	NES.Update(); //Загружаем данные от контроллера NES
	val = NES.Read();
        delta = val ^ prev; //Выявляем изменения
        emulate(); //Эмулируем нажатия
        prev = val; 
}

Переменная delta — отвечает именно за переход состояний. Для работы с игровым контроллером я использовал свою библиотеку NESInterface. В коде назначены следующие клавиши:

  • D-PAD — стрелки
  • Start — буква S
  • Select — буква A
  • A кнопка — буква Z
  • B кнопка — буква X

Работает просто замечательно, проблема может приключится только с драйверами.

Вы можите оставить комментарий, или поставить трэкбек со своего сайта.

Есть 6 коммент. к “USB эмуляция клавиатуры или NES-USB”

  1. Uzix:

    А что за игра на видео? Очень похожа на Ghosts’n’Goblins, но такой версии я не видел.

    Thumb up 0 Thumb down 0

  2. Интересный проект. Возможно ли библиотеку NESInterface использовать для управления несколькими (например двумя) джойстиками?

    Thumb up 0 Thumb down 0

  3. Роман:

    Всем привет!
    А как сделать из USB клавиатуры — Bluetooth клавиатуру (для планшетника или смартфона).
    У меня есть Bluetooth модуль для ардуино. Может кто видел статьи на эту тему?

    Thumb up 0 Thumb down 0

Написать комментарий

XHTML: Вы можете использовать эти теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Bug Report
Локализовано: шаблоны Wordpress