Eu amo jogos de computador antigos. Adoro ferro velho, mas não o suficiente para coletá-lo em casa. Outra coisa é pegar um chip antigo e tentar reproduzir alguma coisa você mesmo, combinar o antigo com o novo. Neste artigo, a história é sobre como eu conectei o microcontrolador AVR ao YM3812, que foi usado em placas de som como Adlib, Sound Blaster e Pro AudioSpectrum. Não criei algo fundamentalmente novo, simplesmente combinei idéias diferentes. Talvez alguém esteja interessado na minha implementação. Ou talvez minha experiência leve alguém a criar seu próprio projeto retrô.

Andando pela Internet, um dia me deparei com um interessante projeto OPL2 Audio Board para Arduino e Raspberry Pi . Em resumo: conecte uma placa ao Arduino ou Raspberry Pi, carregue um esboço ou software, respectivamente, ouça. A idéia tentadora de escolher o chip OPL2, ouvir como ele soa e tentar fazer algo próprio não me deixou, e eu pedi, montei e comecei a descobrir como ele funciona.
Algumas palavras sobre o gerenciamento de chips YM3812
Para que a música toque, precisamos definir registros. Alguns são responsáveis por afinar os instrumentos, outros por tocar notas, etc. O endereço do registro é 8 bits. O valor do registro é 8 bits. Uma lista de registros é fornecida na especificação .
Para transferir os registradores, devemos definir corretamente as leituras nas entradas de controle CS, RD, WR e A0 e no barramento de dados D0..D7.
A entrada CS é necessária para bloquear o barramento de dados durante sua instalação. Defina CS = 1 (desligue a entrada), defina D0..D7, defina CS = 0 (ligue).
A entrada RD deve ser a unidade lógica
Para escrever o endereço do registro, defina WR = 0, A0 = 0
Para escrever o valor do registro, defina WR = 0, A0 = 1
Placa de áudio OPL2 para Arduino e Raspberry Pi

Procedimento de transferência de registro:
- Durante a inicialização, defina PB2 = 1 para bloquear a entrada do
YM3812
- Passamos o endereço de registro
2.1 PB1 = 0 (A0 = 0)
2.2 Nós transmitimos os bytes do endereço de registro através da interface SPI. Os dados são armazenados no registro de turno 74595
2.3 PB2 = 0 (WR = 0, CS = 0). O chip 7404 inverte o sinal e fornece 1 à entrada do ST_CP 74595
, que alterna suas saídas Q0..Q7. YM3812
grava endereço de registro
2,4 PB2 = 1 (WR = 1, CS = 1) - Passamos o valor do registro
3.1 PB1 = 1 (A0 = 1)
3.2 Transferimos bytes de dados através da interface SPI de maneira semelhante à p.2.2
3.3 PB2 = 0 (WR = 0, CS = 0). YM3812
grava dados
3,4 PB2 = 1 (WR = 1, CS = 1)
Um inversor 7404
e quartzo XTAL1
implementam um gerador de pulsos retangular com uma frequência de 3,579545 MHz, necessária para a operação do YM3812
.
YM3014B
converte um sinal digital em um sinal analógico, que é amplificado pelo amplificador operacional LM358
.
O amplificador de áudio LM386
necessário para que alto-falantes ou fones de ouvido passivos possam ser conectados ao dispositivo, como LM358
energia do LM358
não é suficiente.
Agora vamos tentar extrair o som de tudo isso. A primeira coisa que pensei (e provavelmente não apenas eu) foi como fazer tudo funcionar no DosBox. Infelizmente, jogar fora da caixa com o hardware Adlib não funcionará, porque O DosBox não sabe nada sobre o nosso dispositivo e não sabe como transmitir comandos OPL2 em qualquer lugar (até o momento).
O autor do projeto oferece um esboço para Teensy, trabalhando como um dispositivo MIDI. Naturalmente, o som será composto por instrumentos pré-compilados e o som será diferente; obteremos uma emulação de um dispositivo MIDI em um chip OPL2. Não tenho Teensy e não pude experimentar esta opção.
Operação de porta serial
Há um esboço SerialPassthrough . Com ele, podemos transmitir comandos através da porta serial. Resta apenas implementar o suporte no DoxBox. Eu usei a versão do SVN: svn://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk
No src/hardware/adlib.cpp
a implementação do OPL2:
#include "serialport/libserial.h" namespace OPL2 { #include "opl.cpp" struct Handler : public Adlib::Handler { virtual void WriteReg( Bit32u reg, Bit8u val ) {
Antes da montagem, substitua o número da porta COM pelo atual.
Se você remover o comentário na linha //adlib_write(reg,val);
, o som será reproduzido simultaneamente pelo emulador e pelo dispositivo.
Na configuração do DosBox, você precisará especificar o uso do OPL2:
[sblaster] oplemu=compat oplmode=opl2
Aqui está como eu entendi:
Parece bastante volumoso. Mesmo se você usar o Arduino em vez da tábua de pão, precisará conectar os fios. O número da porta no sistema pode mudar e você precisará reconstruir o DosBox. Eu realmente queria trazer tudo para uma aparência concisa, remover peças desnecessárias e montar tudo em uma placa.
OPL2-USB
Surgiu uma idéia e por que não fazer um dispositivo independente com o mínimo de componentes e problemas quando conectado. Primeiro, você pode remover o 74595
e usar as portas atmega. Aqui é usado apenas para reduzir o número de fios. Em segundo lugar, você pode usar um oscilador de cristal pronto e se livrar do chip 7404
. Um amplificador de áudio também não é necessário se você conectar o dispositivo aos alto-falantes. E, finalmente, você pode se livrar do USB-UART se conectar o atmega ao USB diretamente, por exemplo, usando a biblioteca V-USB: https://www.obdev.at/products/vusb/index.html . Para não se preocupar em escrever drivers e instalá-los, você pode tornar o microcontrolador um dispositivo HID personalizado.

As portas B e C estão parcialmente ocupadas conectando-se ao programador do ISP e ao quartzo. A porta D permaneceu completamente livre, usamos para transferência de dados. Eu designei as portas restantes no processo de design da PCB.
O esquema completo pode ser estudado aqui: https://easyeda.com/marchukov.ivan/opl2usb
LED1
com seu resistor é opcional e durante a montagem não os instalei. O fusível U4 é necessário para não queimar acidentalmente a porta USB. Também não pode ser definido, mas substituído por um jumper.
Para compactar o dispositivo, decidi montá-lo em componentes SMD.
Placas de circuito impresso e dispositivo acabado Parte digital à esquerda, analógica à direita.
Para mim, esta foi a primeira experiência em projetar e montar um dispositivo acabado e não poderia prescindir de batentes. Por exemplo, os furos nos cantos da placa devem ter 3 mm de diâmetro para os racks, mas foram 1,5 mm.
O firmware pode ser visualizado no github . Na versão anterior, um comando foi enviado em um pacote USB. Em seguida, verificou-se que, em faixas dinâmicas, o DosBox começa a desacelerar devido à grande sobrecarga e à baixa velocidade do USB 1.0, o DosBox fica impedido de enviar um pacote e receber uma resposta. Eu tive que fazer uma fila assíncrona e enviar comandos em lotes. Isso adicionou um pequeno atraso, mas não é perceptível.
Configuração V-USB
Se já descobrimos o envio de dados para o YM3812 anteriormente, o USB terá que mexer.
Renomeie usbconfig-prototype.h
para usbconfig.h
e adicione-o (abaixo estão apenas as edições):
No arquivo main.c
, definimos as estruturas de dados do pacote
Declarar um identificador para HID
PROGMEM const char usbHidReportDescriptor[] = {
Manipuladores de eventos:
Eu recomendo estes artigos em russo sobre o V-USB:
http://microsin.net/programming/avr-working-with-usb/avr-v-usb-tutorial.html
http://we.easyelectronics.ru/electro-and-pc/usb-dlya-avr-chast-2-hid-class-na-v-usb.html
Suporte do DosBox
O código do DosBox pode ser visualizado no mesmo repositório .
Para trabalhar com o dispositivo no lado do PC, usei a biblioteca hidlibrary.h
(infelizmente, não encontrei links para o original), que precisou ser modificada um pouco.
Decidi não tocar no emulador OPL, mas implementar minha própria classe separada. A mudança para USB nas configurações agora fica assim:
[sblaster] oplemu=usb
No construtor do módulo Adlib em adlib.cpp
adicione a condição:
else if (oplemu == "usb") { handler = new OPL2USB::Handler(); } else {
E no dosbox.cpp
nova opção de configuração:
const char* oplemus[]={ "default", "compat", "fast", "mame", "usb", 0};
O exe compilado pode ser obtido aqui: https://github.com/deadman2000/usb_opl2/releases/tag/0.1
Vídeo
Dispositivo pronto em açãoConexão:
Som gravado através de uma placa de som:
Resultados e planos
Fiquei satisfeito com o resultado. É fácil conectar o dispositivo, sem problemas. Obviamente, minhas modificações no DosBox nunca entrarão na versão oficial e em ramos populares, como Esta é uma solução muito específica.
O próximo na fila é escolher o OPL3. Ainda existe uma ideia para construir um rastreador em chips OPL
Projetos similares
VGM Player
Placa de som OPL2 no barramento ISA