A ligação elétrica é muito simples: o Arduino fornece a alimentação da placa através dos pinos +5V e GND e os sinais de controle da placa são ligados às portas digitais 3 a 7 do Arduino.
Como primeiro teste, vamos programar o KC89C72 para soar um tom de 523Hz (um dó). As informações de programação estão no datasheet, basicamente precisamos escrever valores apropriados nos registradores do KC89C72. A escrita em um registrador é feita através dos seguintes passos, lembrando que temos um shift register 595 ligado à via de dados do KC:
- Os sinais BC1 e BCDIR são colocados em zero para colocar a via de dados no modo inativo (alta impedância).
- O endereço do registrador é colocado na via. Para isto é preciso colocar o sinal Latch do 595 em nível baixo, colocar os bits um a um no sinal Data, pulsando o sinal Clock a cada bit (para colocar o endereço dentro do 595) e depois colocar o sinal Latch no nível alto para o 595 atualizar os seus pinos de dados com o valor que foi enviado serialmente.
- Os sinais BC1 e BCDIR sãi colocados em um, para o KC registrar o dado na via como um endereço de registrador.
- Os sinais BC1 e BCDIR são retornados a zero para voltar a via de dados ao modo inativo.
- O sinal BC1é mantido em zero e BCDIR colocado em um para inciar a escrita no registrador.
- O valor a ser escrito é colocado na via, de volta igual à feita com o endereço.
- Os sinais BC1 e BCDIR são retornados a zero para concluir a escrita.
Os registradores 0 e 1 definem a frequência (ou o período se preferirem) do tom que será emitido no canal A. O KC89C72 pega o sinal de clock (2MHz), divide por 16 e depois divide pelo valor de 12 bits que está nestes registradores. Portanto, para gerar uma frequência f, precisamos programar o valor 2MHz/16/f. O valor zero é usado para gerar silêncio (na realidade o KC89C72 gera uma frequência muito alta).
O registrador 7 determina quais canais de tom e ruído estão inibido, no nosso caso queremos inibir tudo menos o tom do canal A. Este registrador determina também o uso das portas de I/O adicionais (não usadas na placa), vamos deixá-las como entradas.
O registrador 10 determina o volume do canal A e o uso ou não do envelope. Vamos programar a amplitude máxima, sem envelope.
Para não perturbar muito, vamos usar a serial do Arduino para ligar e desligar o tom. O programa está abaixo e pode ser baixado dos arquivos do blog (KC89C72_A.zip).
// Teste com KC89C72 / AY-3-8910 // Conexões da placa de teste ao Arduino const int pinData = 5; const int pinLatch = 6; const int pinClock = 7; const int pinBC1 = 10; const int pinBCDIR = 12; // Frequencia do clock do KC89C72 const long freqKC = 2000000L; // Registradores do KC89C72 const unsigned char regToneA_Lo = 0; const unsigned char regToneA_Hi = 1; const unsigned char regToneB_Lo = 2; const unsigned char regToneB_Hi = 3; const unsigned char regToneC_Lo = 4; const unsigned char regToneC_Hi = 5; const unsigned char regNoisePeriod = 6; const unsigned char regEnable = 7; const unsigned char regAmpA = 8; const unsigned char regAmpB = 9; const unsigned char regAmpC = 10; const unsigned char regEnv_Lo = 11; const unsigned char regEnv_Hi = 12; const unsigned char regEnvShape = 13; // iniciação void setup () { // configura direção dos pinos pinMode(pinLatch, OUTPUT); pinMode(pinData, OUTPUT); pinMode(pinClock, OUTPUT); pinMode(pinBC1, OUTPUT); pinMode(pinBCDIR, OUTPUT); // inicia o KC89C72 writeReg (regNoisePeriod, 0); // desliga noise generator writeReg (regEnable, 0x3E); // somente Tom no A writeReg (regToneA_Lo, 0); // desliga o tom writeReg (regToneA_Hi, 0); writeReg (regAmpA, 0x0F); // amplitude máxima, sem envelope // incia a serial Serial.begin (9600); Serial.println ("KC89C72"); } // programa principal void loop () { if (Serial.available() > 0) { Serial.read(); // Gerar um dó - 523Hz long val = ((freqKC/16L) / 523L); Serial.println (val); writeReg (regToneA_Lo, (unsigned char) (val & 0xFF)); writeReg (regToneA_Hi, (unsigned char) ((val >> 8) & 0xFF)); while (Serial.available() == 0) ; Serial.read(); // Encerra o tom writeReg (regToneA_Lo, 0); writeReg (regToneA_Hi, 0); } } // rotina para escrever um valor em um registrador do KC89C72 void writeReg (unsigned char reg, unsigned char valor) { // coloca no modo inativo digitalWrite(pinBC1, LOW); digitalWrite(pinBCDIR, LOW); // Coloca na via o endereço do registrador digitalWrite(pinLatch, LOW); shiftOut(pinData, pinClock, MSBFIRST, reg); digitalWrite(pinLatch, HIGH); // indica escrita de endereço digitalWrite(pinBC1, HIGH); digitalWrite(pinBCDIR, HIGH); // volta ao modo inativo digitalWrite(pinBC1, LOW); digitalWrite(pinBCDIR, LOW); // indica escrita de dado digitalWrite(pinBC1, LOW); digitalWrite(pinBCDIR, HIGH); // Coloca na via o valor do registrador digitalWrite(pinLatch, LOW); shiftOut(pinData, pinClock, MSBFIRST, valor); digitalWrite(pinLatch, HIGH); // volta ao modo inativo digitalWrite(pinBC1, LOW); digitalWrite(pinBCDIR, LOW); }Sofisticando um pouco, vamos gerar vários tons e tocar uma musiquinha conforme o caractere recebido pela serial ((KC89C72_B.zip nos arquivos do blog). As alterações no programa são:
unsigned freq[7] = {523, 587, 659, 698, 784, 880, 988 }; unsigned nota[7]; int musica[] = { 0, 1, 2, 3, 3, 3, 0, 1, 0, 1, 1, 1, 0, 4, 3, 2, 2, 2, 0, 1, 2, 3, 3, 3, -1 }; // iniciação void setup () { // ... // calcula programação das notas for (int i = 0; i < 7; i++) { nota[i] = (unsigned) ((freqKC/16L) / (long) freq[i]); } } // programa principal void loop () { int c; if (Serial.available() > 0) { c = Serial.read(); if ((c >= '1') && (c <= '7')) { writeReg (regToneA_Lo, (unsigned char) (nota[c-'1'] & 0xFF)); writeReg (regToneA_Hi, (unsigned char) ((nota[c-'1'] >> 8) & 0xFF)); delay (500); writeReg (regToneA_Lo, 0); writeReg (regToneA_Hi, 0); } else if (c == ' ') { for (int i = 0; musica[i] != -1; i++) { int n = musica[i]; writeReg (regToneA_Lo, (unsigned char) (nota[n] & 0xFF)); writeReg (regToneA_Hi, (unsigned char) ((nota[n] >> 8) & 0xFF)); delay (500); writeReg (regToneA_Lo, 0); writeReg (regToneA_Hi, 0); delay (200); } } } }No próximo post vamos brincar um pouco com o gerador de ruídos.
Um comentário:
Uma experiência bacana seria fazer um tocador portátil de arquivos .AY - populares em micros como Sinclair ZX Spectrum e Atari ST. Bastaria incluir um leitor de cartões SD e um display LCD de duas linhas e pronto!
Postar um comentário