Interface do Arduino na porta de fita do C64

8

Atualização : uma implementação prática disso é feita no projeto Tapuino feito por Peter Edwards. Confira, tudo é de código aberto: https://github.com/sweetlilmre/tapuino


Estou trabalhando em um projeto em que estou usando meu Arduino para transmitir arquivos de dados de fita TAP do meu PC para o C64. O lado do software do projeto está indo bem, no entanto, ainda sou novo em eletrônica e não gosto de fritar meu Commodore. Então, eu preciso de ajuda de interface de hardware, na verdade.

As fitas C64 usam modulação PWM para armazenar o programa em fita cassete e, ao ler os dados, um gatilho opamp + schmitt converte o sinal de áudio em ondas quadradas. Cada transição alto-baixo aciona uma interrupção na máquina e a distância entre duas interrupções (que é o comprimento do pulso) representa uma parte atômica do fluxo.

A pinagem da porta cassete fica assim (o lado superior e o lado inferior têm os mesmos pinos duas vezes):

Porta de fita do C64

A-1 , GND, terra

B-2 , + 5V, 5 Volt DC

C-3 , MOTOR, Controle do motor, aprox. Fonte de alimentação de 6 volts do motor

D-4 , READ, Entrada de dados, ler dados do conjunto de dados

E-5 , WRITE, Saída de dados, gravar dados no conjunto de dados

F-6 , SENSE, Detecção, se uma das teclas PLAY, RECORD, F.FWD ou REW for pressionada

Minha ideia atual é a seguinte:

Com base no C64 Interfacing Blue Book (a partir da página 29), a máquina usa o nível TTL na porta READ e WRITE, portanto, acho que posso conectar diretamente um pino PWM do Arduino ao pino READ.

Eu também preciso fazer interface com o pino SENSE. Eu acho que posso conectar diretamente isso também a um dos PINs digitais e escrever digitalmente LOW quando precisar sinalizar o estado do botão pressionado. Isso está correto?

Mais tarde, desejo detectar a presença do sinal de + 6V no pino MOTOR. Alguns carregadores param o conjunto de dados no meio do processo de carregamento, então eu tenho que detectar isso também para emular a fita corretamente. Devo usar algum tipo de resistor para limitar a corrente lá ou posso ligar isso diretamente também? Talvez eu deva usar um relé lá?

NagyI
fonte
O sinal PWM do Arduino vai para o pino WRITE (não READ).
Telaclavo
Eu gosto de emular o conjunto de dados com o Arduino, por isso devo interagir com o pino READ, porque é aí que o C64 aceita entrada.
Nagyi
Pelo que entendi, o formato dos dados não repete os pulsos como um sinal PWM clássico - mas é a combinação de pulsos longos, médios e longos que carregam os dados. O Arduino pode enviar sinais PWM assim?
31915 Johncloud

Respostas:

4

De acordo com o documento que você forneceu, a porta do conjunto de dados está procurando um sinal digital puro com ciclo de trabalho variável (0,75 para H, 0,25 para L).

Enquanto o pino do Arduino puder gerar corrente suficiente (deve) e estiver operando a 5V, uma conexão direta funcionará. Você pode querer investigar o uso de um buffer TTL entre o Arduino e o C64 (o buffer seria alimentado a partir da fonte +5 da porta do conjunto de dados, e o terreno seria comum ao C64 e ao Arduino).

Quanto ao SENSE, seria mais fácil usar uma saída digital para acionar um MOSFET de pequeno sinal (como um 2N7002) - uma lógica alta liga o MOSFET, que puxa o pino SENSE (conectado ao dreno) para o terra (conectado para a fonte) sem que o Arduino precise afundar qualquer corrente.

O pino MOTOR também pode ser usado para acionar uma porta MOSFET. O dreno seria puxado para a tensão de alimentação do Arduino com um pullup fraco (10k ou mais), a fonte conectada ao terra. O dreno também iria para um pino de lógica digital. Quando MOTOR está alto, a entrada lógica é baixa e vice-versa, e o Arduino vê um sinal lógico limpo.

Por exemplo...

Arduino para C64 V1

Observe o uso de dois portões NAND como uma espécie de buffer. (Você pode dizer que eu costumava procurar peças?)

TTL é bastante robusto. Não acho que haja muita chance de danificar nada.

Adam Lawrence
fonte
Uau, bons esquemas. Acho que vou tentar conectar o pino de saída PWM do Arduino diretamente ao D-4 primeiro porque ele usa 5V também. De qualquer forma, obrigado! :)
NagyI
@ NagyI Deve funcionar.
Adam Lawrence
Oh meu Deus, eu não aceitei esta resposta? Que vergonha. Enfim, acabei de pedir o conector da borda da fita para tentar isso e minha estação de solda chega na próxima semana. Por isso espero que eu possa testar isso em breve :)
Nagyi
Por não ter conseguido um 2N7002, meu colega me sugeriu o BS170. A sinalização de sentido funciona perfeitamente. No entanto, a detecção do motor está interrompida. O Arduino sempre lê a lógica baixa. Não importa se eu coloco Gate em Low ou High, o Arduino sempre lê lógica baixa. Esse é o problema do BS170 ou algo diferente? Eu tentei com outro BS170, mas o problema permanece. Parece-me que o BS170 só pode alternar GND, mas não tensão.
precisa saber é o seguinte
2

Soa como um projeto interessante. Lembro-me de que o hardware do VIC-20 alimentou pulsos do Datasette em um circuito de detecção de borda (esqueço se ele detectou subidas ou descidas); as rotinas de carregamento de fita C64 eram compatíveis com as do VIC-20, portanto, não acho que o carregador padrão possa ter usado truques que o VIC-20 não suportaria, embora os carregadores personalizados possam. Eu nunca brinquei com as coisas naquele dia o suficiente para determinar se o Datasette convertia as bordas ascendentes e descendentes em pulsos (por exemplo, alimentando um sinal atrasado e não atrasado em um portão XOR). Criei uma rotina para converter dados em larguras de pulso, mas nunca descobri como usar o detector de borda.

No que diz respeito à obtenção de dados do PC para o C64, se você não quiser usar uma placa de som (algumas placas de som têm processamento de imagem estéreo e podem causar estragos na fase do áudio de saída), existem duas abordagens: pode sugerir: (1) enviar dados do intervalo de pulso do PC para o Arduino e simplesmente ter os pulsos de saída individuais no tempo do Arduino. Talvez codifique o formato de dados com dois pulsos por byte, usando algo como a seguinte codificação:

0000-1100 - gera uma saída de 20us seguida de baixa de 24-60us (em múltiplos de 3us)
1101 - Saída 40us baixa
1110 - Saída 80us baixa
1111 - Valores de bytes de $ FF serão ignorados
          - Outros byes com um nybble igual a 1111 podem ser usados ​​para simular o
             botões do motor de fita ou indique uma indicação "ok para pausar aqui".

Não acho que nenhum esquema de carregamento tente cronometrar pulsos com precisão superior a 3us, e esse esquema permitiria que os dados fossem enviados por um UART em 115200. O PC deve adicionar bytes de preenchimento 0xFF para que a taxa na qual os dados sejam enviados para o Arduino corresponderá razoavelmente bem à taxa em que o Arduino está atingindo o clock. Como cada nybble levará entre 44 e 80 microssegundos para processar, o Arduino precisaria apenas pesquisar seu UART entre nybbles e poderia desativar as interrupções perto do final de cada pulso. Se o PC agrupar seus dados de maneira razoavelmente eficaz, pode-se (1) fazer com que o PC tente enviar dados um pouco mais rápido do que o Arduino produziria e usar o handshaking de hardware ou software para desacelerá-lo, ou (2) fazer o Arduino retire um microssegundo de cada pulso quando seu buffer estiver quase cheio, ou adicione um microssegundo a cada pulso quando seu buffer estiver quase vazio. Para evitar falhas de áudio resultantes de soluços momentâneos do PC, o Arduino suspende a saída com um byte "ok para pausar aqui" se o buffer não estiver quase cheio.

supercat
fonte
Obrigado pelas idéias. Na verdade, estou transmitindo os dados do arquivo TAP diretamente para o Arduino. Ele especifica cada pulso com um byte. (veja: c64tapes.org/dokuwiki/doku.php?id=analyzing_loaders ) Para superar os problemas da transferência de dados, estou usando um buffer circular de um kB no Arduino que está sendo preenchido no loop principal. Os dados são consumidos pela função de interrupção anexada ao evento de correspondência do gerador PWM. Isso é chamado duas vezes por pulso. É aí que estou alterando o nível do PIN e, na transição alto-baixo, estou escrevendo o novo valor do registro de correspondência de acordo com o próximo byte.
Nagyi