Created
August 10, 2025 01:49
-
-
Save zr0n/825212a7e489349739fefc05135beb27 to your computer and use it in GitHub Desktop.
Como transformar controle de tv antigo em joystick
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Arduino.h> | |
#include <IRremoteESP8266.h> | |
#include <IRrecv.h> | |
#include <IRutils.h> | |
const uint8_t IR_PIN = 13; | |
IRrecv irrecv(IR_PIN, 1024, 15, true); | |
decode_results results; | |
void setup() { | |
Serial.begin(115200); | |
delay(200); | |
irrecv.enableIRIn(); | |
Serial.println("Sniffer IR pronto. Aponte o controle e pressione botoes..."); | |
} | |
void loop() { | |
if (irrecv.decode(&results)) { | |
Serial.println(resultToHumanReadableBasic(&results)); | |
if (results.decode_type != decode_type_t::UNKNOWN) { | |
Serial.print("Codigo HEX: 0x"); | |
Serial.println((uint32_t)results.value, HEX); | |
} | |
irrecv.resume(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Arduino.h> | |
#include <BleGamepad.h> | |
#include <IRremoteESP8266.h> | |
#include <IRrecv.h> | |
#include <IRutils.h> | |
#ifndef GAMEPAD_HAT_CENTERED | |
#define GAMEPAD_HAT_CENTERED (-1) | |
#define GAMEPAD_HAT_UP 0 | |
#define GAMEPAD_HAT_RIGHT 2 | |
#define GAMEPAD_HAT_DOWN 4 | |
#define GAMEPAD_HAT_LEFT 6 | |
#endif | |
static const uint8_t IR_PIN = 13; | |
BleGamepadConfiguration bleCfg; | |
BleGamepad bleGamepad("Joystick de Pobre", "Kovil", 100); | |
IRrecv irrecv(IR_PIN, 1024, 15, true); // timeout 15ms | |
decode_results results; | |
struct IRToAction { uint32_t code; enum Type { HAT, BTN } type; int value; }; | |
static const IRToAction mapTable[] = { | |
{ 0x02FD41BE, IRToAction::HAT, GAMEPAD_HAT_UP }, | |
{ 0x02FDC13E, IRToAction::HAT, GAMEPAD_HAT_DOWN }, | |
{ 0x02FD9867, IRToAction::HAT, GAMEPAD_HAT_RIGHT }, | |
{ 0x02FDB847, IRToAction::HAT, GAMEPAD_HAT_LEFT }, | |
{ 0x02FD40BF, IRToAction::BTN, 4 }, | |
{ 0x02FDB847, IRToAction::BTN, 3 }, | |
{ 0x02FD609F, IRToAction::BTN, 2 }, | |
{ 0x02FDE817, IRToAction::BTN, 1 }, | |
{ 0x02FD807F, IRToAction::BTN, 5 }, | |
{ 0x02FDE01F, IRToAction::BTN, 7 }, | |
{ 0x02FDC03F, IRToAction::BTN, 6 }, | |
{ 0x02FD906F, IRToAction::BTN, 8 }, | |
}; | |
static const size_t MAP_COUNT = sizeof(mapTable)/sizeof(mapTable[0]); | |
struct HoldState { uint32_t code; uint32_t lastSeenMs; bool active; }; | |
static HoldState holds[MAP_COUNT]; | |
static const uint32_t HOLD_TIMEOUT_MS = 180; | |
static int currentHat = GAMEPAD_HAT_CENTERED; | |
static int lastIdx = -1; | |
static bool lastConnected = false; | |
static uint32_t hbLast = 0; | |
int findMapIndex(uint32_t code){ for(size_t i=0;i<MAP_COUNT;i++) if(mapTable[i].code==code) return (int)i; return -1; } | |
void sendNow(const char* tag){ | |
if(bleGamepad.isConnected()){ bleGamepad.sendReport(); Serial.printf("[BLE] sendReport (%s)\n", tag); } | |
else Serial.println("[BLE] not connected, skipped sendReport"); | |
} | |
void pressAction(int idx){ | |
const auto &m = mapTable[idx]; | |
if(m.type==IRToAction::HAT){ currentHat=m.value; bleGamepad.setHat(currentHat); Serial.printf("[BLE] HAT=%d (code=0x%08lX)\n", currentHat,(unsigned long)m.code); } | |
else { bleGamepad.press(m.value); Serial.printf("[BLE] PRESS BTN_%d (code=0x%08lX)\n", m.value,(unsigned long)m.code); } | |
holds[idx].active=true; holds[idx].lastSeenMs=millis(); sendNow("pressAction"); | |
} | |
void releaseAction(int idx){ | |
const auto &m = mapTable[idx]; | |
if(!holds[idx].active) return; | |
if(m.type==IRToAction::HAT){ if(currentHat==m.value){ currentHat=GAMEPAD_HAT_CENTERED; bleGamepad.setHat(currentHat); Serial.printf("[BLE] HAT=CENTER (code=0x%08lX)\n",(unsigned long)m.code); } } | |
else { bleGamepad.release(m.value); Serial.printf("[BLE] RELEASE BTN_%d (code=0x%08lX)\n", m.value,(unsigned long)m.code); } | |
holds[idx].active=false; sendNow("releaseAction"); | |
} | |
void releaseExpiredHolds(){ | |
const uint32_t now=millis(); | |
for(size_t i=0;i<MAP_COUNT;i++){ | |
if(holds[i].active && (now-holds[i].lastSeenMs)>HOLD_TIMEOUT_MS){ | |
Serial.printf("[BLE] timeout -> release idx=%d code=0x%08lX\n",(int)i,(unsigned long)mapTable[i].code); | |
releaseAction(i); | |
} | |
} | |
} | |
void setup(){ | |
Serial.begin(115200); | |
uint32_t t0=millis(); while(!Serial && millis()-t0<2000) delay(10); | |
Serial.printf("\n[BOOT] start. IR_PIN=%d\n", IR_PIN); | |
irrecv.enableIRIn(); | |
Serial.println("[BOOT] IR ready (NEC)"); | |
bleCfg.setControllerType(CONTROLLER_TYPE_GAMEPAD); | |
bleCfg.setButtonCount(16); | |
bleCfg.setHatSwitchCount(1); | |
bleCfg.setAutoReport(false); | |
Serial.println("[BOOT] BLE begin..."); | |
bleGamepad.begin(&bleCfg); | |
Serial.println("[BOOT] BLE ready. Pair now."); | |
} | |
void loop(){ | |
if(millis()-hbLast>1000){ hbLast=millis(); Serial.println("[HB] alive"); } | |
bool c=bleGamepad.isConnected(); if(c!=lastConnected){ Serial.printf("[BLE] connected=%d\n",(int)c); lastConnected=c; } | |
if(irrecv.decode(&results)){ | |
uint32_t code=(uint32_t)results.value; | |
bool isNEC=(results.decode_type==decode_type_t::NEC || results.decode_type==decode_type_t::NEC_LIKE); | |
Serial.printf("[IR] type=%d code=0x%08lX repeat=%d\n",(int)results.decode_type,(unsigned long)code,(int)results.repeat); | |
if(isNEC){ | |
bool isRepeat=results.repeat || code==0xFFFFFFFF; | |
if(isRepeat){ | |
if(lastIdx>=0){ Serial.printf("[IR] repeat -> reapply idx=%d code=0x%08lX\n",lastIdx,(unsigned long)mapTable[lastIdx].code); pressAction(lastIdx); } | |
else Serial.println("[IR] repeat with no lastIdx"); | |
}else{ | |
int idx=findMapIndex(code); | |
if(idx>=0){ lastIdx=idx; Serial.printf("[IR] mapped idx=%d\n",idx); pressAction(idx); } | |
else Serial.printf("[IR] unmapped 0x%08lX\n",(unsigned long)code); | |
} | |
}else{ | |
Serial.println("[IR] non-NEC ignored"); | |
} | |
irrecv.resume(); | |
} | |
releaseExpiredHolds(); | |
delay(2); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment