/* KVMote — Arduino Leonardo (Serial1 = HC-06) Baud rate: 9600 (padrão de fábrica do HC-06). Se você já configurou o HC-06 para outra velocidade via AT commands, altere a constante abaixo. Protocolo binário: Mouse move → 'M' dx(int8) dy(int8) 3 bytes Mouse wheel → 'W' delta(int8) 2 bytes Tecla write → 'K' char 2 bytes Clique → 'C' 'L'|'R' 2 bytes Tecla press → 'P' keycode 2 bytes Tecla release → 'U' keycode 2 bytes ReleaseAll → 'A' 1 byte Mouse press → 'D' 'L'|'R' 2 bytes Mouse release → 'E' 'L'|'R' 2 bytes LED cliente → 'O' (laranja — entrou no cliente) LED host → 'H' (flash verde + volta azul — voltou ao host) Ping/Pong → '~' → responde [PONG] 1 byte */ #include #include // ── Pinos do LED RGB ────────────────────────────────────────────────────────── #define PIN_R 5 #define PIN_G 6 #define PIN_B 9 #define BAUD_HC06 9600 // ← altere se necessário // ── Cor base do LED (muda conforme o modo) ──────────────────────────────────── uint8_t basR = 0, basG = 0, basB = 255; // azul = idle // ── Máquina de estados ──────────────────────────────────────────────────────── enum Estado : uint8_t { AGUARDA_CMD, AGUARDA_MOUSE_DX, AGUARDA_MOUSE_DY, AGUARDA_MOUSE_WHEEL, AGUARDA_TECLA, AGUARDA_CLIQUE, AGUARDA_PRESS_KEY, AGUARDA_RELEASE_KEY, AGUARDA_MOUSE_PRESS, AGUARDA_MOUSE_RELEASE }; Estado estado = AGUARDA_CMD; int8_t pendingDX = 0; // ── Helpers de LED ──────────────────────────────────────────────────────────── void ledCor(int r, int g, int b) { analogWrite(PIN_R, r); analogWrite(PIN_G, g); analogWrite(PIN_B, b); } void piscaVerde() { ledCor(0, 200, 0); delay(40); ledCor(basR, basG, basB); // retorna à cor base atual } void piscaCiano() { ledCor(0, 200, 200); delay(40); ledCor(basR, basG, basB); // retorna à cor base atual } // ── Setup ───────────────────────────────────────────────────────────────────── void setup() { Serial1.begin(BAUD_HC06); Keyboard.begin(); Mouse.begin(); ledCor(basR, basG, basB); // azul = pronto } // ── Loop principal (non-blocking) ───────────────────────────────────────────── void loop() { while (Serial1.available() > 0) { byte b = (byte)Serial1.read(); switch (estado) { // ── Aguarda o byte de comando ────────────────────────────────────────── case AGUARDA_CMD: if (b == 'M') estado = AGUARDA_MOUSE_DX; else if (b == 'W') estado = AGUARDA_MOUSE_WHEEL; else if (b == 'K') estado = AGUARDA_TECLA; else if (b == 'C') estado = AGUARDA_CLIQUE; else if (b == 'P') estado = AGUARDA_PRESS_KEY; else if (b == 'U') estado = AGUARDA_RELEASE_KEY; else if (b == 'D') estado = AGUARDA_MOUSE_PRESS; else if (b == 'E') estado = AGUARDA_MOUSE_RELEASE; else if (b == 'A') { Keyboard.releaseAll(); piscaVerde(); } else if (b == 'O') { // Entrou no PC cliente → LED laranja basR = 255; basG = 80; basB = 0; ledCor(basR, basG, basB); } else if (b == 'H') { // Voltou ao host → flash verde, LED azul basR = 0; basG = 0; basB = 255; piscaVerde(); } else if (b == '~') { Serial1.print("[PONG]"); piscaCiano(); } // qualquer outro byte é silenciosamente descartado break; // ── Mouse: lê DeltaX ────────────────────────────────────────────────── case AGUARDA_MOUSE_DX: pendingDX = (int8_t)b; estado = AGUARDA_MOUSE_DY; break; // ── Mouse: lê DeltaY e executa o movimento ──────────────────────────── case AGUARDA_MOUSE_DY: Mouse.move(pendingDX, (int8_t)b, 0); estado = AGUARDA_CMD; // Sem piscaVerde() aqui — delay(40) bloquearia o processamento serial break; // ── Mouse: roda do mouse ────────────────────────────────────────────── case AGUARDA_MOUSE_WHEEL: Mouse.move(0, 0, (int8_t)b); estado = AGUARDA_CMD; break; // ── Teclado: lê o caractere e digita (write) ────────────────────────── case AGUARDA_TECLA: Keyboard.write(b); estado = AGUARDA_CMD; piscaVerde(); break; // ── Clique: lê L ou R e clica ───────────────────────────────────────── case AGUARDA_CLIQUE: if (b == 'L') Mouse.click(MOUSE_LEFT); if (b == 'R') Mouse.click(MOUSE_RIGHT); estado = AGUARDA_CMD; piscaVerde(); break; // ── Tecla press (mantém pressionada) ───────────────────────────────── case AGUARDA_PRESS_KEY: Keyboard.press(b); estado = AGUARDA_CMD; piscaVerde(); break; // ── Tecla release ───────────────────────────────────────────────────── case AGUARDA_RELEASE_KEY: Keyboard.release(b); estado = AGUARDA_CMD; piscaVerde(); break; // ── Mouse press (botão segurado) ────────────────────────────────────── case AGUARDA_MOUSE_PRESS: if (b == 'L') Mouse.press(MOUSE_LEFT); if (b == 'R') Mouse.press(MOUSE_RIGHT); estado = AGUARDA_CMD; piscaVerde(); break; // ── Mouse release ───────────────────────────────────────────────────── case AGUARDA_MOUSE_RELEASE: if (b == 'L') Mouse.release(MOUSE_LEFT); if (b == 'R') Mouse.release(MOUSE_RIGHT); estado = AGUARDA_CMD; piscaVerde(); break; } } }