Горячее
Лучшее
Свежее
Подписки
Сообщества
Блоги
Эксперты
Войти
Забыли пароль?
или продолжите с
Создать аккаунт
Я хочу получать рассылки с лучшими постами за неделю
или
Восстановление пароля
Восстановление пароля
Получить код в Telegram
Войти с Яндекс ID Войти через VK ID
Создавая аккаунт, я соглашаюсь с правилами Пикабу и даю согласие на обработку персональных данных.
ПромокодыРаботаКурсыРекламаИгрыПополнение Steam
Пикабу Игры +1000 бесплатных онлайн игр
🔥 Дрифт и гонки без правил!
Садись за руль, жги резину и уноси баллы в безумных поворотах!
🚗 Реалистичный дрифт
🏁 Захватывающие трассы
💨 Улучши свою тачку и побеждай!

Дрифт Без Лимита

Гонки, Симуляторы, Спорт

Играть

Топ прошлой недели

  • AlexKud AlexKud 38 постов
  • SergeyKorsun SergeyKorsun 12 постов
  • SupportHuaport SupportHuaport 5 постов
Посмотреть весь топ

Лучшие посты недели

Рассылка Пикабу: отправляем самые рейтинговые материалы за 7 дней 🔥

Нажимая кнопку «Подписаться на рассылку», я соглашаюсь с Правилами Пикабу и даю согласие на обработку персональных данных.

Спасибо, что подписались!
Пожалуйста, проверьте почту 😊

Помощь Кодекс Пикабу Команда Пикабу Моб. приложение
Правила соцсети О рекомендациях О компании
Промокоды Биг Гик Промокоды Lamoda Промокоды МВидео Промокоды Яндекс Директ Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня

Arduino + Планшет

С этим тегом используют

Электроника Ardublock Самоделки YouTube Своими руками Вертикальное видео Видео ВК Помощь Android Рисунок Смартфон Ремонт Гаджеты Кот Все
1 пост сначала свежее
194
monobogdan
monobogdan
2 года назад
TECHNO BROTHER

Сам себе игровая консоль: превращаем планшет с нерабочим тачскрином в игровой девайс из 8 кнопок и микроконтроллера⁠⁠

Сам себе игровая консоль: превращаем планшет с нерабочим тачскрином в игровой девайс из 8 кнопок и микроконтроллера Смартфон, Телефон, Идея, Своими руками, Arduino, Embedded, Встраиваемые системы, Планшет, Игры, Консоли, Самоделки, Моддинг, Android, Linux, Java, C++, Kernel, Покупка, Raspberry pi, Микроконтроллеры, Видео, Длиннопост

К сожалению, в наше время многие старые, но весьма неплохие по характеристикам гаджеты отправляются напрямую в помойку, и их владельцы не подозревают, что им можно найти применение. Сервер, мультимедийная-станция, да даже просто как TV-приставка — люди в упор не замечают сфер, где старенький планшет мог бы быть полезен. Но как быть, если посвящаешь жизнь портативным гаджетам, кодингу и копанию в железе? Правильно: сделать довольно мощную игровую консоль из старого планшета самому! Сегодня вам расскажу, как я сделал свою портативную приставку из планшета с нерабочим тачскрином, Raspberry Pi Pico и 8 кнопок! За рабочим результатом прячется несколько дней работы: поиск UART на плате, разработка контроллера геймпада на базе RPi Pico, написание приложения-сервиса, которое слушает события и отправляет их в подсистему ввода Linux в обход Android. Интересно? Тогда жду вас под катом!

❯ Мотивация


Прошло уже практически 10 лет с того момента, как у меня появилась моя первая портативная консоль. Несмотря на то, что я был заядлым ПК-игроком, я уже успел посмотреть на PS3 и PSP, но денег на их покупку у меня особо не было, да и к тому времени уже был в наличии Android-планшет. Но к моему 13-летию в 2014 году, когда я ходил и выбирал себе будущий девайс на день рождения, отец и мама решили подарить мне мою первую портативную консоль. Изначально, я уговаривал её купить мне целых два девайса, но бюджет был ограничен 4.000 рублей, а я хотел взять смартфон Fly IQ239 и консоль JXD S601 одновременно:

Сам себе игровая консоль: превращаем планшет с нерабочим тачскрином в игровой девайс из 8 кнопок и микроконтроллера Смартфон, Телефон, Идея, Своими руками, Arduino, Embedded, Встраиваемые системы, Планшет, Игры, Консоли, Самоделки, Моддинг, Android, Linux, Java, C++, Kernel, Покупка, Raspberry pi, Микроконтроллеры, Видео, Длиннопост


Однако, увидев здоровую 7-дюймовую консоль в магазине TREC (думаю, жители южной части РФ помнят такой), мама уговорила меня взять именно её, мотивируя это «ну и чего ты будешь тыкаться в этот мелкий экран? Возьми большую». После покупки гаджета, я был доволен: играл какие-то игрушки с ретро-платформ, устанавливал игры на Android, сидел в ВК через Kate Mobile. Что еще нужно было школяру? Однако, планшет прожил у меня недолго: с очередного лага я психанул и ударил по нему кулачком, унеся на тот свет и дисплей и тачскрин. Так консолька и пролежала в подвале около 8 лет. Впрочем, мне продолжали импонировать подобные устройства и в прошлом году я купил и написал про несколько подобных девайсов.

Сам себе игровая консоль: превращаем планшет с нерабочим тачскрином в игровой девайс из 8 кнопок и микроконтроллера Смартфон, Телефон, Идея, Своими руками, Arduino, Embedded, Встраиваемые системы, Планшет, Игры, Консоли, Самоделки, Моддинг, Android, Linux, Java, C++, Kernel, Покупка, Raspberry pi, Микроконтроллеры, Видео, Длиннопост



Несколько месяцев назад, мой читатель Кирилл Севостьянов с Хабра прислал мне HTC HD2 в качестве донора и планшет Prestigio PMP7170B3G, который был рабочим, но… у него отказал тачскрин. Я всё думал, чего бы с ним сделать и решил реализовать игровую консольку своими руками из подручных средств. Идея крутилась в голове довольно давно, но реализовал я её только сейчас.

❯ Что нам нужно сделать?


Итак, что должно быть у портативной консоли? Чипсет, дисплей, звук, ОС — это всё нам уже предоставляет планшет. Нам остаётся лишь сделать свой геймпад. Давайте подумаем, что нам будет нужно для того, чтобы его сделать и передавать от него события на планшет:

  • Контроллер для геймпада: тут нам подойдет практически любой микроконтроллер, который работает от 3.3в. Выбор большой: Arduino Pro Mini 3.3v, ESP32, RPi Pico. Я остановился на последнем: недавно я взял себе две штучки «пощупать» их — и они мне очень понравились!

  • Физический интерфейс: с планшетом нужно как-то общаться. У нас есть три варианта: USB (не факт, что поддержка преобразователей включена в ядре), UART и SPI/I2C на пятачках тачскрина (потребуют написания драйвера т. к. в android-устройствах нет прямого доступа к SPI/I2C из userland'а). Я остановился на UART: его легко найти на большинстве китайских планшетов, а если не получилось — то на помощь может прийти схема платы.

  • Программная реализация: как это будет работать? Я решил реализовать геймпад в виде сервиса на Android, который слушает состояния кнопок с UART и «инжектит» события напрямую в драйвер ввода. Таким образом, поддержка нашего геймпада появляется даже в самой системе — можно управлять менюшкой или приложениями как с клавиатуры!


    С планом определились, пора начать с программной части: сначала нам обязательно понадобится ROOT-доступ. Его получение на разных девайсах отличается — на prestigio уже был порт CWM и я просто поставил SuperSU. Без ROOT доступа мы не сможем использовать UART!

Сам себе игровая консоль: превращаем планшет с нерабочим тачскрином в игровой девайс из 8 кнопок и микроконтроллера Смартфон, Телефон, Идея, Своими руками, Arduino, Embedded, Встраиваемые системы, Планшет, Игры, Консоли, Самоделки, Моддинг, Android, Linux, Java, C++, Kernel, Покупка, Raspberry pi, Микроконтроллеры, Видео, Длиннопост


Теперь нам нужно найти пятачки UART на плате. Разведен он не везде, но в случае устройств на MediaTek — почти всегда, ещё и пятачки подписаны. На моём планшете он нашёлся сразу: был между двух металлических экранов и соответствовал 4-ому каналу UART. Получить к нему доступ можно в /dev/ttyMT3. Я использую ESP32 в качестве UART преобразователя: подпаиваемся к RX/TX, запускаем putty и заходим в adb shell. Определяем бодрейт (скорость) нашего UART порта — на MediaTek он обычно равен 921600, на других чипсетах — 115200. Пытаемся что-то вывести и хоба — мы уже можем «поболтать» с планшетом!

Сам себе игровая консоль: превращаем планшет с нерабочим тачскрином в игровой девайс из 8 кнопок и микроконтроллера Смартфон, Телефон, Идея, Своими руками, Arduino, Embedded, Встраиваемые системы, Планшет, Игры, Консоли, Самоделки, Моддинг, Android, Linux, Java, C++, Kernel, Покупка, Raspberry pi, Микроконтроллеры, Видео, Длиннопост

❯ Приложение-сервис


Итак, у нас уже есть доступ к UART и мы можем общаться с планшетом из внешнего мира. Но получить события с кнопок пол дела, нужно их ещё и послать в систему. Для этого есть целых три способа:

  1. InputManager.injectInputEvent — именно этим методом пользуется команда input, которую вы можете использовать через adb. Но увы, он работает только при наличие разрешения INJECT_EVENTS, который доступен только системным приложениям — находятся они в /system/app и подписаны тем же сертификатом, что и остальная прошивка.

  2. Модуль uinput дает возможность создать виртуальное устройство ввода и посылать события из userland'а — т. е. из прикладного приложения. У моего планшета было устройство /dev/uinput, но lsmod показывал, что сам модуль не загружен. Так что отметаем — он есть не везде.

  3. Прямой инжект событий в character устройство — весьма грязный хак, который позволяет инжектить события, не притворяясь системным приложением, но имеет некоторые ограничения. Именно его я и выбрал и о ограничениях ниже.


Сначала нам нужно узнать, какие кнопки поддерживают загруженные устройства ввода в системе. Для этого используем команду getevent -li. Там есть разные устройства ввода, в том числе и тачскрин (если вам нужно симулировать нажатия на экран), мне же подошёл драйвер физических кнопок mtk-kpd. Он занимается обработкой кнопок громкости, включения и т. п. Тут важно обратить внимание на то, что если попытаться послать кнопку, которое устройство не реализует (например пробел), то ничего не произойдет:

Сам себе игровая консоль: превращаем планшет с нерабочим тачскрином в игровой девайс из 8 кнопок и микроконтроллера Смартфон, Телефон, Идея, Своими руками, Arduino, Embedded, Встраиваемые системы, Планшет, Игры, Консоли, Самоделки, Моддинг, Android, Linux, Java, C++, Kernel, Покупка, Raspberry pi, Микроконтроллеры, Видео, Длиннопост



Инжект событий я писал на C, т. к. это требовало прямой записи input_event, а в Java прокинул его через Jni. Концепция простая: открываем устройство /dev/input/event2 и посылаем в него события ввода и синхронизации (это обязательно!), которые затем Android читает и обрабатывает:

#include <linux/uinput.h>

#include <fcntl.h>

#include <unistd.h>

#include <stdio.h>

#include <stdlib.h>

#include <android/log.h>

#include <jni.h>

int uinput;

extern "C" JNIEXPORT void JNICALL Java_com_monobogdan_inputservicebridge_InputNative_init(JNIEnv *env, jclass clazz) {

uinput = open("/dev/input/event2", O_WRONLY);

__android_log_print(ANDROID_LOG_DEBUG , "Test", uinput >= 0 ? "Open event OK" : "Failed to open event"); }

void emit(int fd, int type, int code, int val) {

struct input_event ie; ie.type = type;

ie.code = code; ie.value = val;

ie.time.tv_sec = 0;

ie.time.tv_usec = 0;

write(fd, &ie, sizeof(ie)); }

extern "C" JNIEXPORT void JNICALL Java_com_monobogdan_inputservicebridge_InputNative_sendKeyEvent(JNIEnv *env, jclass clazz, jint key_code, jboolean pressed) {

__android_log_print(ANDROID_LOG_DEBUG , "Test", "Send");

emit(uinput, EV_KEY, key_code, (bool)pressed ? 1 : 0);

emit(uinput, EV_SYN, SYN_REPORT, 0);

}

Основной обработкой занимается сервис, который я реализовал в отдельном потоке: он слушает события с UART и посылает соответствующие изменения состояния через sendKeyEvent. На вход приходят простые сообщения вида:

U L где U/D — нажато, не нажато, а L — однобайтовый идентификатор кнопки. В случае L — это влево, R — вправо и т. п. Вся доступная раскладка хранится в словаре. Причём само чтение из UART реализовано костылем с чтением «чужого» stdout, т. к. android-приложения не умеют сами по себе работать с root правами. В теории, это могло дать неприятный оверхед, но на практике никакого серьезного инпут лага это не создает. Не забываем сделать устройство event записываемым — ставим ему права 777:

package com.monobogdan.inputservicebridge;

public class InputListener extends Service {

private static final int tty = 3;

private InputManager iManager;

private Map<Character, Integer> keyMap;

private Method injectMethod;

private Process runAsRoot(String cmd)

{

try {

return Runtime.getRuntime().exec(new String[] { "su", "-c", cmd });

}

catch (IOException e)

{

e.printStackTrace();

return null;

}

}

@override

public void onCreate() {

super.onCreate();

// According to linux key map (input-event-codes.h)

keyMap = new HashMap<>();

keyMap.put('U', 103);

keyMap.put('D', 108);

keyMap.put('L', 105);

keyMap.put('R', 106);

keyMap.put('E', 115);

keyMap.put('B', 158);

keyMap.put('A', 232);

keyMap.put('C', 212);

InputNative.init();

try {

runAsRoot("chmod 777 /dev/input/event2").waitFor();

} catch (InterruptedException e) {

throw new RuntimeException(e);

}

Executors.newSingleThreadExecutor().execute(new Runnable() {

@override

public void run() {

Process proc = runAsRoot("cat /dev/ttyMT" + tty);

BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));

while(true)

{

try {

String line = reader.readLine();

if(line != null && line.length() > 0) {

Log.i("Hi", "run: " + line);

boolean pressing = line.charAt(0) == 'D';

int keyCode = keyMap.get(line.charAt(2));

Log.i("TAG", "run: " + keyCode);

InputNative.sendKeyEvent(keyCode, pressing);

}

}

catch(IOException e)

{

e.printStackTrace();

}

/*try {

Thread.sleep(1000 / 30);

} catch (InterruptedException e) {

e.printStackTrace();

}*/

}

}

});

}

@override

public IBinder onBind(Intent intent) {

return null;

}

}

Таким образом, если мы отправляем с ПК «D L» — система считает, что мы зажали стрелку влево, а U L — считает что мы отпустили. Но если mtk-kpd поддерживает стрелки и еще некоторые действия без каких либо проблем, то enter в список обрабатываемых кнопок не входит: придется мудрить! И тут нам приходит на помощь механизм трансляции кодов кнопок в действия: они хранятся в специальных файлах .kl в /system/usr/keylayout/. Я назначил DPAD_CENTER на… кнопку регулировки громкости звука! Ну, а почему бы и нет. :) Таким образом можно переназначить уже имеющиеся кнопки громкости на, например, start/select.

Сам себе игровая консоль: превращаем планшет с нерабочим тачскрином в игровой девайс из 8 кнопок и микроконтроллера Смартфон, Телефон, Идея, Своими руками, Arduino, Embedded, Встраиваемые системы, Планшет, Игры, Консоли, Самоделки, Моддинг, Android, Linux, Java, C++, Kernel, Покупка, Raspberry pi, Микроконтроллеры, Видео, Длиннопост

❯ Геймпад


После того, как сервис был готов и отлажен, нужно было реализовать хардварную часть проекта — сам геймпад. В качестве контроллера я, как уже говорил, выбрал Raspberry Pi Pico на базе МК RP2040 — бодреньком контроллере с двумя ARM Cortex-M0 ядрами. Стоит копейки, а в отличии от ESP'шек, его SDK не такое перегруженное и выглядит более приближенным к bare-metal.

Сам себе игровая консоль: превращаем планшет с нерабочим тачскрином в игровой девайс из 8 кнопок и микроконтроллера Смартфон, Телефон, Идея, Своими руками, Arduino, Embedded, Встраиваемые системы, Планшет, Игры, Консоли, Самоделки, Моддинг, Android, Linux, Java, C++, Kernel, Покупка, Raspberry pi, Микроконтроллеры, Видео, Длиннопост



На данный момент, я решил развести все кнопки на бредборде — макетной плате без пайки, т. к. макеток для пайки у меня под рукой не было. Сделал примитивный геймпад:

Сам себе игровая консоль: превращаем планшет с нерабочим тачскрином в игровой девайс из 8 кнопок и микроконтроллера Смартфон, Телефон, Идея, Своими руками, Arduino, Embedded, Встраиваемые системы, Планшет, Игры, Консоли, Самоделки, Моддинг, Android, Linux, Java, C++, Kernel, Покупка, Raspberry pi, Микроконтроллеры, Видео, Длиннопост



Развел на соответствующие GPIO:

Сам себе игровая консоль: превращаем планшет с нерабочим тачскрином в игровой девайс из 8 кнопок и микроконтроллера Смартфон, Телефон, Идея, Своими руками, Arduino, Embedded, Встраиваемые системы, Планшет, Игры, Консоли, Самоделки, Моддинг, Android, Linux, Java, C++, Kernel, Покупка, Raspberry pi, Микроконтроллеры, Видео, Длиннопост



И написал примитивную прошивку, которая отслеживает состояние кнопок. В прошивке точно так же есть словарь, задающий ассоциацию между физическими пинами и «виртуальными» кнопками. При нажатии или отжатии кнопки, программа изменяет стейт и отсылает новое состояние планшету.

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include "pico/stdlib.h"

#include "pico/time.h"

#include "hardware/uart.h"

struct keyMap

{

int gpio;

char key;

bool pressed;

int lastTick;

};

keyMap keys[] = {

{

15,

'L',

false,

0

},

{

14,

'U',

false,

0

},

{

13,

'D',

false,

0

},

{

12,

'R',

false,

0

},

{

11,

'E',

false,

0

},

{

10,

'B',

false,

0

},

{

20,

'A',

false,

0

},

{

21,

'C',

false,

0

}

};

#define KEY_NUM 8

int main() {

stdio_init_all();

uart_init(uart0, 921600);

gpio_set_function(PICO_DEFAULT_UART_TX_PIN, GPIO_FUNC_UART);

gpio_set_function(PICO_DEFAULT_UART_RX_PIN, GPIO_FUNC_UART);

sleep_ms(1000); // Allow serial monitor to settle

for(int i = 0; i < KEY_NUM; i++)

{

gpio_init(keys[i].gpio);

gpio_set_dir(keys[i].gpio, false);

gpio_pull_up(keys[i].gpio);

}

while(true)

{

int now = time_us_32();

for(int i = 0; i < KEY_NUM; i++)

{

char buf[5];

buf[1] = ' ';

buf[3] = '\n';

buf[4] = 0;

if(!gpio_get(keys[i].gpio) && !keys[i].pressed && now - keys[i].lastTick > 15500)

{

buf[0] = 'D';

buf[2] = keys[i].key;

puts(buf);

keys[i].lastTick = now;

keys[i].pressed = true;

continue;

}

if(gpio_get(keys[i].gpio) && keys[i].pressed && now - keys[i].lastTick > 15500)

{

buf[0] = 'U';

buf[2] = keys[i].key;

puts(buf);

keys[i].pressed = false;

keys[i].lastTick = now;

}

}

}

}

Собираем всё вместе и тестируем. Хоба, всё работает, мы можем перемещаться по менюшке используя наш геймпад!

Сам себе игровая консоль: превращаем планшет с нерабочим тачскрином в игровой девайс из 8 кнопок и микроконтроллера Смартфон, Телефон, Идея, Своими руками, Arduino, Embedded, Встраиваемые системы, Планшет, Игры, Консоли, Самоделки, Моддинг, Android, Linux, Java, C++, Kernel, Покупка, Raspberry pi, Микроконтроллеры, Видео, Длиннопост



А почему бы не попробовать поиграть в какую-нибудь игру? Ну мы же консоль вроде делаем: берём эмулятор NES, биндим кнопки в настройках и наслаждаемся игрой в Марио!

❯ Заключение


Реализация этого проекта заняла у меня не так уж и много времени: всего около 3-х дней работы по вечерам. Вероятно кто-то спросит: «а чего ты просто Bluetooth геймпад не купил?». Так это не прикольно ведь. Гораздо приятнее играть в девайс, к которому ты приложил руку сам. Более того, не у всех старых планшетов есть BT. Обошёлся на данной стадии проект недорого: планшет мне подарили бесплатно (точно также у вас дома может лежать подобный), RPi Pico — 350 рублей, кнопки по 10 рублей/штучка.

В целом, я сам по себе обожаю копаться в различных железках и их софтварной части (вспомнить хотя-бы статью про перекомпиляциюu-boot из вендорских исходников для нонейм консоли), а созидать что-то свое вообще вызывает какие-то нереальные всплески эндорфина — оно и понятно! :)

Однако несмотря на то, что мы уже имеем рабочий «прототип», проект далёк от завершения: я намерен довести его до конца и окончательно перевоплотить старый планшет в автономную игровую консоль (и рассказать об этом во второй части статьи). Для этого мне понадобится распечатать корпус и кнопки на 3D-принтере. К сожалению, у меня в городе ни у кого особо нет 3D-принтеров, поэтому начну копить на Ender 3, а от вас, читателей, с удовольствием почитаю мнение в комментариях и советы касательно выбора принтера!

Статья подготовлена при поддержке TimeWeb Cloud. Подписывайтесь на меня и @Timeweb.Cloud, чтобы не пропускать еженедельные статьи про моддинг различных гаджетов!

Показать полностью 10 1
[моё] Смартфон Телефон Идея Своими руками Arduino Embedded Встраиваемые системы Планшет Игры Консоли Самоделки Моддинг Android Linux Java C++ Kernel Покупка Raspberry pi Микроконтроллеры Видео Длиннопост
33
Посты не найдены
О нас
О Пикабу Контакты Реклама Сообщить об ошибке Сообщить о нарушении законодательства Отзывы и предложения Новости Пикабу Мобильное приложение RSS
Информация
Помощь Кодекс Пикабу Команда Пикабу Конфиденциальность Правила соцсети О рекомендациях О компании
Наши проекты
Блоги Работа Промокоды Игры Курсы
Партнёры
Промокоды Биг Гик Промокоды Lamoda Промокоды Мвидео Промокоды Яндекс Директ Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня
На информационном ресурсе Pikabu.ru применяются рекомендательные технологии