Close

AVR Pong in C/C++

A project log for AVR Pong in Assembly

Final Project of "AVR: Architecture, Assembly & Reverse Engineering" HackADayU Course

rijo-abrahamRijo Abraham 03/10/2021 at 17:510 Comments

Wokwi Arduino Simulator


uint8_t frame[8][2];
/* x : +ve right ; columns ; (0,15)
 * y : +ve down  ; rows    ; (1,8)*/
int8_t x=1, y=3, py=3, cy=3, dx=-1, dy=1;

void spi_transfer(uint8_t data)
{
  SPDR = data;
  while(!bitRead(SPSR, SPIF));
}

void draw_frame() {
  for (int row=1; row<=8; row++)
  {
    /* Enable CS */
    bitClear(PORTB, 2);
    spi_transfer(row);
    spi_transfer(frame[row-1][0]);
    spi_transfer(row);
    spi_transfer(frame[row-1][1]);
    /* Disable CS */
    bitSet(PORTB, 2);
  }
}

void clear_frame() {
  for (int row=1; row<=8; row++)
  {
    frame[row-1][0] = frame[row-1][1] = 0x00; 
  }

  draw_frame();
}

void setup() {
  /* Initialize SPI */
  bitSet(SPCR, SPE); /* SPI Enable */
  bitSet(SPCR, MSTR); /* Master */

  /* Configure SPI CS pin (PB2) */
  bitSet(DDRB, 2);
  bitSet(PORTB, 2);

  /* Configure pin change interrupt on pins PD6 (PCINT22) and PD7 (PCINT23) */
  DDRD = 0x00; /* Configure pins as input */
  PORTD = 0xFF; /* Enable pull up  resistors */
  bitSet(PCICR, PCIE2); /* Enable PCINT[23:16] */
  bitSet(PCMSK2, PCINT22); /* Unmask pin change interrupt on PD6*/
  bitSet(PCMSK2, PCINT23); /* Unmask pin change interrupt on PD7 */

  /* Timer 1 Configuration */
  TCCR1A = 0x00; /* Normal operation */
  TCCR1B = 0x00; 
  /* f1 = f_clk/64 = 16M/64 */
  /* T1 = 64/16 us = 4 us */
  bitSet(TCCR1B, CS10); /* 64 prescaler */ 
  bitSet(TCCR1B, CS11);
}

void update_player_paddle() {
  if (!bitRead(PIND, 7)) /* Paddle up */ py -= 1;
  if (!bitRead(PIND, 6)) /* Paddle down */ py += 1;

  if (py < 1) py = 1;
  if (py > 6) py = 6;
}

ISR(PCINT2_vect) {
  /* Push button debouncing */
  /* 50 ms = 50,000 us, Count = 50,000/4 = 12,500 */
  TCNT1 = 53035; /* 65535 - 12,500 */
  bitSet(TIMSK1, TOIE1); /* Enable overflow interrupt */
}

ISR(TIMER1_OVF_vect) {
  update_player_paddle();

  bitClear(TIMSK1, TOIE1); /* Disable overflow interrupt */
}

uint8_t count = 0;

void loop() {
  if (x==1) {
    if ((y < py) || (y > py+2)) {
      /* "GAME OVER!" */
      while(1);
    }
  }

  clear_frame();
  if (y==1) dy=1; else if (y==8) dy=-1;
  if (x==1) dx=1; else if (x==14) dx=-1;

  y = y + dy;
  x = x + dx;

  /* Computer Paddle AI */ 
  if (x > 7) cy = y;
  if (cy < 1) cy = 1;
  if (cy > 6) cy = 6;

  /* Ball */ 
  bitSet(frame[y-1][x/8], x%8); 
  /* Player Paddle */
  bitSet(frame[py-1][0], 0);
  bitSet(frame[py][0], 0);
  bitSet(frame[py+1][0], 0);
  /* Computer Paddle*/
  bitSet(frame[cy-1][1], 7);
  bitSet(frame[cy][1], 7);
  bitSet(frame[cy+1][1], 7);

  draw_frame(); 

  // update_player_paddle();
  delay(100);
  // update_player_paddle();
  delay(100);
}

Discussions