// Definindo os pinos de endereço, dados e controle
const int addressPins[] = {22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37};
const int dataPins[] = {38, 39, 40, 41, 42, 43, 44, 45};
const int RW = 46;
const int PHI2 = 47;
const int RESET = 48;

// Exemplo de programa binário (8 bytes)
const byte program[] = {0xA9, 0x42, 0x8D, 0x80, 0x00};

// Função para configurar o Timer 3 para gerar o sinal de clock
void setupClockSignal() {
  // Configurar o pino 47 como saída
  pinMode(47, OUTPUT);

  // Configurar o Timer 3 no modo Fast PWM, com prescaler de 1
  TCCR3A = (1 << COM3B0) | (1 << WGM31) | (1 << WGM30);
  TCCR3B = (1 << WGM33) | (1 << WGM32) | (1 << CS30);

  // Definir o valor do registrador de comparação para obter um clock de ~1 MHz
  OCR3B = 7;
}

void setup() {
  // Inicialize a comunicação serial
  Serial.begin(9600);

  // Configurando pinos de endereço, dados e controle
  for (int i = 0; i < 16; i++) {
    pinMode(addressPins[i], OUTPUT);
  }

  for (int i = 0; i < 8; i++) {
    pinMode(dataPins[i], OUTPUT);
  }

  pinMode(RW, OUTPUT);
  pinMode(PHI2, OUTPUT);
  pinMode(RESET, OUTPUT);

  // Configurar o sinal de clock
  setupClockSignal();

  // Reset no 6502
  digitalWrite(RESET, LOW);
  delay(10);
  digitalWrite(RESET, HIGH);
  delay(10);

  // Enviando o programa para o 6502
  for (int i = 0; i < sizeof(program); i++) {
    setAddress(i);
    setData(program[i]);
    digitalWrite(RW, LOW); // Escrever na memória
    digitalWrite(PHI2, HIGH);
    delayMicroseconds(1);
    digitalWrite(PHI2, LOW);
    delayMicroseconds(1);
  }

  // Aguarde um momento para o 6502 executar o programa
  delay(1000);

  // Definindo o endereço de memória que você deseja ler
  unsigned int memoryAddressToRead = 0x80; // Substitua este valor pelo endereço de memória que você deseja ler

  // Configurando os pinos de dados como entrada
  for (int i = 0; i < 8; i++) {
    pinMode(dataPins[i], INPUT);
  }

  // Lendo o valor no endereço de memória especificado
  setAddress(memoryAddressToRead);
  digitalWrite(RW, HIGH); // Ler da memória
  digitalWrite(PHI2, HIGH);
  delayMicroseconds(1);
  byte valueRead = getData();
  digitalWrite(PHI2, LOW);
  delayMicroseconds(1);

  // Imprimindo o valor lido usando Serial.print()
  Serial.print("Valor lido no endereço 0x");
  Serial.print(memoryAddressToRead, HEX);
  Serial.print(": 0x");
  Serial.println(valueRead, HEX);
}

void loop() {
  // Neste exemplo, o loop principal não faz nada.
}

void setAddress(unsigned int address) {
  for (int i = 0; i < 16; i++) {
    digitalWrite(addressPins[i], (address >> i) & 0x01);
  }
}

void setData(byte data) {
  for (int i = 0; i < 8; i++) {
    digitalWrite(dataPins[i], (data >> i) & 0x01);
  }
}

byte getData() {
  byte data = 0;
  for (int i = 0; i < 8; i++) {
    data |= digitalRead(dataPins[i]) << i;
  }
  return data;
}
$abcdeabcde151015202530354045505560fghijfghij
MOS 6502 CPUBreakout