Skip to content
SchickackaPublic

About

Firmware customizado de alta performance para receptor BlueRetro no PlayStation 1 (ESP32): LED inteligente, rumble 8BitDo, modo noturno e fix de reset.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

BlueRetro — PlayStation 1 Custom Edition (v0.7.5.1)

BlueRetro Logo

GitHub Release Build Status Platform ESP32 Bluetooth License


Visão Geral

O BlueRetro — PlayStation 1 Custom Edition é um firmware customizado de alta precisão para receptores Bluetooth baseados em ESP32 (DevKit V1 / ESP-WROOM-32) voltado ao console Sony PlayStation 1 (testado em PU-8 late 1-658-467-21; a pinagem é a mesma nas demais revisões).

Baseado no projeto de Jacques Gagnon (BlueRetro), esta edição foi desenvolvida e mantida por Schickacka com o objetivo de implementar calibrações eletromecânicas fiéis às especificações do controle DualShock original (SCPH-1200), robustez de concorrência em tempo real e estabilidade total de feedback em controladores sem fio modernos (DualShock 4 e DualSense).


Arquitetura e Configurações de Hardware

1. Limiar Eletromecânico e Elevação do Piso Ativo do Atuador de Baixa Frequência (0x40 / 64)

  • Comportamento do Hardware Original: No controle físico DualShock 1 (SCPH-1200), o motor esquerdo (baixa frequência) é composto por um contrapeso excêntrico de ferro maciço alimentado pela linha de 7.6V do console. Devido ao atrito estático e à inércia mecânica desse conjunto, comandos com sinal PWM inferior a 0x40 (64 em decimal) não produzem torque de partida suficiente para girar o motor físico, permanecendo completamente imóvel no hardware com fio original.
  • Compatibilidade e Inércia em Controles Paralelos e Modernos: Jogos de PlayStation 1 frequentemente emitem valores residuais contínuos de baixa amplitude (< 0x40) nos registradores de feedback como ruído de fundo ou nível de linha de base. Em controladores sem fio modernos e controles paralelos equipados com atuadores de 3.7V, esses valores residuais faziam o contrapeso girar continuamente se não fossem filtrados. Adicionalmente, em controles clones/paralelos, a inércia estática e atrito mecânico dos micromotores frequentemente atenuavam ou impediam a percepção física de pulsos muito curtos (1 a 2 quadros, como disparos pontuais de metralhadora em Resident Evil 3 ou passos leves) quando solicitados no piso de ativação mínimo (64).
  • Calibração e Remapeamento Ativo (v0.7.5.1): Comandos com valores inferiores a 0x40 continuam estritamente tratados como repouso absoluto (0x00), garantindo silêncio cirúrgico entre pulsos. Já a faixa ativa ($\ge 64$) é remapeada de forma linear e contínua do intervalo $[64, 255]$ para $[85, 255]$: $$\text{Power}_{\text{LF}} = \begin{cases} 85 + \left\lfloor \dfrac{(\text{raw} - 64) \times 170 + 95}{191} \right\rfloor, & \text{se } \text{raw} \ge 64 \ 0, & \text{se } \text{raw} < 64 \end{cases}$$ Essa calibração eleva o piso operacional de partida para $85$ (fornecendo torque inicial imediato para vencer o atrito estático em controles paralelos sem atraso perceptível), enquanto preserva intacta a saturação máxima no teto da escala ($\text{raw} = 255 \implies 255$) e a proporcionalidade de intensidade em toda a biblioteca do console.
  • Ativação do Motor de Alta Frequência: O motor direito (leve/alta frequência) é tratado como sinal binário digital, no qual qualquer byte não nulo aciona saturação máxima (0xFF), garantindo resposta tátil nítida e imediata para qualquer intensidade de comando emitida pelo jogo.

2. Transmissão Contínua de Feedback em Alta Frequência (20 ms / 50 Hz)

  • Temporizador Watchdog dos Controles Sem Fio: Os controladores Bluetooth modernos (DualShock 4 e DualSense) possuem um temporizador interno de segurança (watchdog) em seus firmwares de aproximadamente 200 ms a 250 ms. Se os motores estiverem ativos e nenhum novo relatório HID Bluetooth for recebido dentro dessa janela, o controle atenua ou desliga a alimentação dos atuadores por proteção térmica e conservação de bateria.
  • Sustentação de Eventos Hápticos Prolongados: Em situações de vibração contínua e constante (como disparos sustentados de armas automáticas, aceleração contínua em zebras de pista ou explosões de longa duração), o console mantém os mesmos valores nos registradores de comando quadro a quadro. Na ausência de variação nos dados, a rotina de feedback pausava a transmissão por 300 ms, gerando solavancos e microcortes cíclicos causados pelo desarmamento do watchdog interno do controle.
  • Calibração Implementada: A rotina de transmissão Bluetooth (bt_fb_task) monitora atomicamente o estado ativo de vibração (BT_DEV_RUMBLE_ON). Enquanto qualquer controle conectado estiver vibrando, os pacotes de feedback são retransmitidos a cada 20 ms (50 Hz nominais), por temporizador de software. Não há sincronismo com o vídeo do console: o PS1 opera a 59,94 Hz (NTSC/PAL-M) ou 50 Hz (PAL); o período de 20 ms serve apenas para manter vivo o watchdog interno do controle.

3. Interrupção Imediata de Vibração em Pausa e Menus (Comando 0x43)

  • Quando o jogo entra em pausa ou acessa telas de configuração/inventário, o console chaveia a comunicação serial para o comando 0x43. O driver intercepta imediatamente essa transição e emite um pacote de parada forçada com comprimento zero (data_len = 0), desligando os motores de forma instantânea sem resíduos de rotação.

4. Limiar Estendido de Inatividade do Barramento SPI (3,0 Segundos)

  • Durante transições de tela, telas de carregamento do CD-ROM ou reprodução de vídeos em tela cheia (FMV), determinados jogos suspendem temporariamente a comunicação com as portas de controle por mais de um segundo. O limiar de inatividade para reinicialização (PS_IDLE_RESET_US) foi estendido para 3,0 segundos, prevenindo que pausas de leitura do disco desarmem o modo analógico, enquanto preserva a capacidade de detectar com precisão quando o console foi reiniciado pelo botão físico de Reset.

5. Sincronização Imediata de Modo Analógico e Iluminação Balanceada

  • Sincronização na Conexão: Ao ligar o controle no meio de uma partida na qual o console já esteja operando em modo Analógico (0x73), o controle entra diretamente em Analógico e acende a barra de luz na cor correspondente, sem exigir reinicialização do console ou alternância manual.
  • Cores padrão do build de release:
    • Modo Analógico: vermelho #6D0000 (R=0x6D, ≈43% do vermelho máximo).
    • Modo Digital: DualShock 4 em cinza #949190; DualSense com a lightbar apagada (0x000000) e apenas os pontos de jogador acesos.
  • Modo noturno (opcional): só existe com CONFIG_BR_PS1_NIGHT_MODE=y (padrão n). Quando ligado, divide as componentes RGB por 2 e usa o brilho mínimo do DS4/DS5.

6. Sincronização Atômica entre Núcleos (Dual-Core)

  • O firmware distribui suas cargas entre os dois núcleos do ESP32: o Core 1 é responsável pelo driver baremetal SPI em tempo real (ps_spi.c), enquanto o Core 0 gerencia a pilha de protocolos Bluetooth e o sistema operacional FreeRTOS (host.c).
  • As variáveis compartilhadas entre a ISR e as tarefas usam volatile mais barreiras (__sync_synchronize()) ou operações atômicas (atomic_cas) nos pontos de publicação de estado. volatile sozinho não garante atomicidade de campos multi-byte; por isso os campos de estado são de 8/32 bits alinhados e as transições críticas são publicadas com barreira explícita.

7. Desligamento Automático por Inatividade (10 min)

  • Um controle Bluetooth sem botão pressionado, com sticks centrados e sem rumble ativo por 10 minutos é desconectado automaticamente (CONFIG_BR_INACTIVITY_TIMEOUT_MIN; 0 desativa).
  • Contador Atômico Thread-Safe: A contagem de inatividade no loop de manutenção (bt_host_task) utiliza primitivas atômicas nativas da toolchain GCC (__atomic_add_fetch e __atomic_store_n com semântica __ATOMIC_RELAXED) sobre o array de estado dev_idle_sec[BT_MAX_DEV], prevenindo condições de corrida e inconsistências de memória entre tarefas concorrentes do FreeRTOS.
  • Detecção Normalizada por Amplitude de Eixo: Em vez de limiares brutos fixos (que variavam sensivelmente dependendo da resolução nativa de cada modelo de controle), o limiar de atividade analógica é normalizado com base nos metadados de amplitude (axis->meta->abs_max / 5), correspondendo a cerca de 20% do curso real (25 unidades na escala de 8 bits).
  • O console vê o controle desaparecer: jogos que pausam ao perder o controle vão pausar. Basta ligar o controle de novo (botão PS/Home) para reconectar.
  • Ajuste em main/Kconfig.projbuild → menu PS1 Custom Edition → "Controller inactivity timeout in minutes".

8. Reconexão e Inicialização Instantânea (DualShock 4 e DualSense)

  • Resolução Determinística de Nome Bluetooth: Durante a reconexão iniciada pelo próprio controle via paginação (incoming page), o canal de interrupção L2CAP é negociado antes da chegada do pacote de identificação de nome (BT_HCI_EVT_REMOTE_NAME_REQ_COMPLETE). O driver detecta a transição de tipo genérico (BT_HID_GENERIC) para PlayStation (BT_PS), redefine a flag de inicialização e invoca o inicializador nativo do driver (bt_hid_ps_init), garantindo que o controle nunca fique preso em modo genérico.
  • Inicialização Imediata (0 ms de espera adicional): Assim que o controle emite seu primeiro relatório de status completo (Report 0x11 para DualShock 4 ou Report 0x31 para DualSense), a rotina de inicialização cancela o temporizador de fallback com segurança (esp_timer_stop antes de esp_timer_delete), marca o dispositivo como pronto, aciona a vibração de confirmação, inicia o piscar da cor do jogador e disponibiliza a porta do console de forma instantânea.
  • Recuperação de Modo Boot (Report 0x01): Caso o DualShock 4 inicie a transmissão em modo boot genérico (Report 0x01), o firmware emite o comando probe de transição (0xC0, 0x07) para colocá-lo imediatamente em modo nativo Bluetooth.

9. Acesso a Memory Card em Múltiplas Portas (mt_first_port)

  • A verificação do modo de acessórios (acc_mode & ACC_MEM) no driver SPI baremetal é indexada pelo slot raiz da porta física (port->mt_first_port), assegurando que cartões de memória virtuais ou físicos operem de forma consistente na Porta 2 independentemente da configuração de multitap.

Mapeamento de Pinos (Pinout)

Configuração padrão dos pinos de conexão entre a placa ESP32 DevKit V1 e as portas do console:

Sinal PlayStation Pino do Console GPIO ESP32 Observação
P1 DATA (MISO) Pino 1 GPIO 19 ESP32 → console
P1 COMMAND (MOSI) Pino 2 GPIO 32 Console → ESP32
P1 ATT / DTR Pino 6 GPIO 34 Entrada; pull-up externo de 10 kΩ obrigatório (GPIO34 não tem pull-up interno)
P1 CLOCK (SCK) Pino 7 GPIO 33 Console → ESP32
P1 ACK / DSR Pino 9 GPIO 21 ESP32 → console
P2 DATA (MISO) Pino 1 GPIO 22 ESP32 → console
P2 COMMAND (MOSI) Pino 2 GPIO 27 Console → ESP32
P2 ATT / DTR Pino 6 GPIO 5 Entrada com pull-up interno
P2 CLOCK (SCK) Pino 7 GPIO 26 Console → ESP32
P2 ACK / DSR Pino 9 GPIO 25 ESP32 → console
GND (Terra) Pino 4 GND Referência comum
LED Analógico Porta 1 — GPIO 12 Nível alto em modo analógico
LED Analógico Porta 2 — GPIO 15 Nível alto em modo analógico
LED Onboard (Status BT) — GPIO 2 LED azul da placa

Alimentação: não use o pino 5 (3,5 V). Veja "Diretrizes de Alimentação". A fonte da verdade dos GPIOs é main/wired/ps_spi.c (linhas 97–108); se a tabela e o código divergirem, o código ganha.


Diretrizes de Alimentação

Nunca alimente o ESP32 pelo pino 5 (3,5 V) do conector do controle. Essa linha vem da fonte do console, é compartilhada com a lógica das portas de controle e do memory card e é protegida por fusível. O ESP32 pede picos de centenas de mA (rádio Bluetooth em transmissão e calibração de RF no boot) que essa linha não foi dimensionada para fornecer: a tensão afunda, causando brownout reset, e a sobrecarga sostenida abre o fusível — o console perde as portas com fio. Além disso, não há regulador nem proteção entre o pino 5 e o rail de 3,3 V do ESP32, e 3,5 V está no limite superior da faixa de 3,0–3,6 V do chip, sem margem para transitórios.

Fonte correta: pino 3 (7,6 V) + conversor buck DC-DC

  1. Ligue um buck ajustável (ex.: MP1584EN) no pino 3 (7,6 V) e ajuste a saída para 5,0 V (capacidade ≥ 1 A).
  2. Ligue a saída do buck no pino VIN / 5V do ESP32. Não ligue no pino 3.3V: o regulador da placa (AMS1117) precisa de pelo menos 4,5 V na entrada. Em placas DevKitC com AMS1117 (máximo 18 V), o próprio upstream aceita 8 V direto no VIN; o buck é preferível porque o LDO dissipa (8 − 5) × I e esquenta.
  3. Instale 470 µF + 100 nF junto ao ESP32 e um fusível de 1 A no ramo de 7,6 V, o mais próximo possível do ponto de derivação.
  4. O GND do console (pino 4) e o GND do ESP32 devem ser o mesmo nó.

O 7,6 V do conector é a linha não chaveada na maioria das revisões: com o console desligado o ESP32 continua energizado. Se você precisa que ele desligue junto com o console, use o pino 5 (3,5 V) apenas como sinal de enable de um MOSFET / load switch de alta impedância — nunca como fonte de energia.

O pino 5 pode ficar desconectado: ele é saída da console (alimenta a lógica do controle original), não entrada. O ESP32 não precisa dele para nada.

Alternativa: 5 V externo (USB)

Alimente o ESP32 por USB (5 V) e ligue ao console apenas o GND e as linhas de sinal. É a opção mais segura para bancada e para quem não quer mexer na fonte.


Instalação e Atualização do Firmware

Método 1: Atualização Sem Fio via Bluetooth (OTA - Recomendado)

Se o BlueRetro já estiver instalado no console, o procedimento pode ser realizado sem abrir o videogame e sem cabos:

Note

O script de atualização sem fio (ble_ota_update.py) requer a biblioteca Python bleak (pip install bleak).

  1. Baixe o pacote BlueRetro_PS1_Custom_v0.7.5.1_Package.zip na aba Releases.
  2. Ligue o PlayStation 1 com os controles Bluetooth desligados.
  3. Execute o arquivo flash_bluetooth_ota.bat (Windows).
  4. O script localizará o dispositivo via Bluetooth LE e efetuará a gravação em aproximadamente 50 segundos. O receptor reiniciará automaticamente com o firmware atualizado.

Alternativa via Navegador: Acesse blueretro.io/ota.html no Chrome ou Edge, conecte-se ao BlueRetro e envie o arquivo BlueRetro_hw1_playstation.bin.

Método 2: Gravação via Cabo USB (Windows)

  1. Conecte o ESP32 ao computador via cabo micro-USB.
  2. Extraia o conteúdo de BlueRetro_PS1_Custom_v0.7.5.1_Package.zip.
  3. Execute flash_windows.bat e informe a porta serial correspondente (exemplo: COM3, COM4, COM6).

Método 3: Gravação Manual via Linha de Comando (esptool)

python -m esptool --chip esp32 --port COMx -b 921600 --before default_reset --after hard_reset write_flash --flash_mode dio --flash_size 4MB --flash_freq 40m 0x1000 bootloader.bin 0x8000 partition-table.bin 0xd000 ota_data_initial.bin 0x10000 BlueRetro_hw1_playstation.bin

Compatibilidade de Hardware e Controles

Controles Testados

  • Sony DualShock 4 — oficial e clones/paralelos (CUH-ZCT1 e CUH-ZCT2).
  • Sony DualSense (PS5) — atuadores de precisão mapeados para baixa e alta frequência.

Padrões de Feedback e Comportamento em Jogos

O firmware foi projetado e calibrado para atender aos padrões de comunicação e feedback utilizados pela biblioteca do PlayStation:

  • Efeitos de Pulso e Modulação: Resposta de motores pesados com repouso verdadeiro nos intervalos de baixa intensidade (como batimentos cardíacos, avisos de proximidade e alertas de status).
  • Vibração Sustentada Contínua: Disparos prolongados de armas automáticas, aceleração contínua e superfícies acidentadas reduzindo microcortes por watchdog.
  • Transições de Cena e Vídeos: Preservação do modo analógico durante pausas de leitura em FMVs e telas de transição.
  • Resposta de Impacto: Acionamento agudo em golpes, impactos rápidos e colisões.

Compilação a Partir do Código-Fonte

Este repositório possui fluxo automatizado de integração contínua (CI) via GitHub Actions que gera os binários a cada commit na branch master. Para compilação local utilizando o framework ESP-IDF v5.5:

# Clonagem recursiva obrigatória para obtenção de submódulos
git clone --recursive https://github.com/Schickacka/BlueRetro.git
cd BlueRetro

# Gerar arquivo de versão do firmware customizado
echo "v0.7.5.1 ps1-custom" > version.txt

# Carregar arquivo de configuração para PlayStation
cp configs/hw1/playstation sdkconfig

# Compilar binários
BR_HW=_hw1 BR_SYS=_playstation idf.py reconfigure build

Se você baixou o Source.zip (e não clonou com --recursive), rode ./scripts/fetch_liblfds.sh antes do build: o zip não traz o submódulo components/queue_bss/liblfds.


Licença e Créditos

  • BlueRetro: Copyright (c) 2019-2025, Jacques Gagnon. Distribuído sob a licença Apache License 2.0.
  • PlayStation 1 Custom Edition: Desenvolvido e mantido por Schickacka.
  • Todas as alterações de código e adições arquiteturais estão documentadas nos arquivos modificados em conformidade com a seção 4(b) da licença Apache 2.0.

About

Firmware customizado de alta performance para receptor BlueRetro no PlayStation 1 (ESP32): LED inteligente, rumble 8BitDo, modo noturno e fix de reset.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages