Close

AVR Pong in Assembly

A project log for AVR Pong in Assembly

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

rijo-abrahamRijo Abraham 03/12/2021 at 06:150 Comments

Wokwi Arduino Simulator


#define __SFR_OFFSET 0

#include "avr/io.h"

.global main

.data
frame_segment_1: .space 8
frame_segment_2: .space 8

.text
spi_transfer:
  out SPDR, r24
1: 
  in r0, SPSR
  sbrs r0, SPIF
  rjmp 1b
  ret

delay_ms:
  ldi r26, 4000 & 0xFF
  ldi r27, 4000 >> 8
1:
  sbiw r26, 1
  brne 1b
  sbiw 24, 1
  brne delay_ms
  ret

clear_frame:
  ldi ZL, lo8(frame_segment_1)
  ldi ZH, hi8(frame_segment_1)
  ldi YL, lo8(frame_segment_2)
  ldi YH, hi8(frame_segment_2)
  ldi r18, 8
  ldi r19, 0x00
1:
  st Z+, r19
  st Y+, r19
  dec r18
  brne 1b
  
  ret

draw_frame:
  ldi r18, 1
  ldi ZL, lo8(frame_segment_1)
  ldi ZH, hi8(frame_segment_1)
  ldi YL, lo8(frame_segment_2)
  ldi YH, hi8(frame_segment_2)
1:
  ; Enable SPI CS
  ldi r19, 0x00
  out PORTB, r19

  mov r24, r18
  rcall spi_transfer
  ld r24, Z+
  rcall spi_transfer
  mov r24, r18
  rcall spi_transfer
  ld r24, Y+
  rcall spi_transfer

  ; Disable SPI CS
  ldi r19, 0x04
  out PORTB, r19

  inc r18
  cp r18, 8
  brne 1b
  ret

update_player_paddle:
  sbis PIND, 7
  dec r4  ; Move up
  sbis PIND, 6
  inc r4  ; Move down

  ; if py < 1, py = 1
  mov r18, r4
  cpi r18, 1
  brsh 2f
  ldi r18, 1
  mov r4, r18
  brsh 1f
2:
  ; if py >= 7, py = 6
  mov r18, r4
  cpi r18, 6
  brlo 1f
  ldi r18, 6
  mov r4, r18
1:
  ret

main:
  ; Initialize SPI
  ldi r18, 0x50
  out SPCR, r18

  ; Configure SPI CS pin (PB2)
  ldi r18, 0x04
  out DDRB, r18
  ldi r18, 0x04
  out PORTB, r18

  ; Configure pins PD6 and PD7
  ldi r18, 0x00
  out DDRD, r18
  ldi r18, 0xFF
  out PORTD, r18

  ; Initialize variable
  ldi r18, 1
  mov r2, r18  ; Ball x
  ldi r18, 3
  mov r3, r18  ; Ball y
  ldi r18, 3
  mov r4, r18  ; Player paddle (py)
  ldi r18, 3
  mov r5, r18  ; Computer paddle (cy)
  ldi r18, -1
  mov r6, r18  ; Ball velocity (dx)
  ldi r18, 1
  mov r7, r18  ; Ball velocity (dy)

loop:
  ; if y == 1, dy = 1
  mov r18, r3
  cpi r18, 1
  brne 1f
  ldi r19, 1
  mov r7, r19
1:
  ; if y == 8, dy = -1
  cpi r18, 8
  brne 2f
  ldi r19, -1
  mov r7, r19
2:

  ; if x == 1, dx = 1
  mov r18, r2
  cpi r18, 1
  brne 1f
  ldi r19, 1
  mov r6, r19
1:
  ; if x == 14, dx = -1
  cpi r18, 14
  brne 2f
  ldi r19, -1
  mov r6, r19
2:

  ; y += dy
  add r3, r7
  ; x += dx
  add r2, r6

  ; Computer Paddle AI
  ; if x >= 8, cy = y
  mov r18, r2
  cpi r18, 8
  brlo 1f
  mov r5, r3 
  ; if cy < 1, cy = 1
  mov r18, r5
  cpi r18, 1
  brsh 2f
  ldi r18, 1
  mov r5, r18
  brsh 1f
2:
  ; if cy >= 7, cy = 6
  mov r18, r5
  cpi r18, 6
  brlo 1f
  ldi r18, 6
  mov r5, r18
1:

  call clear_frame

  ;; Ball
  mov r18, r2 
  cpi r18, 8
  brsh 1f
  ; frame_segment_1
  ldi ZL, lo8(frame_segment_1)
  ldi ZH, hi8(frame_segment_1)
  mov r19, r2
  inc r19
  ldi r20, 0x00
  bset 0
3:
  rol r20
  bclr 0
  dec r19
  brne 3b
  jmp 2f
1:
  ; frame_segment_2
  ldi ZL, lo8(frame_segment_2)
  ldi ZH, hi8(frame_segment_2)
  mov r19, r2
  subi r19, 7
  ldi r20, 0x00
  bset 0
3:
  rol r20
  bclr 0
  dec r19
  brne 3b
2:
  add ZL, r3
  adc ZH, r1
  st -Z, r20

  ;; Player Paddle
  ldi ZL, lo8(frame_segment_1)
  ldi ZH, hi8(frame_segment_1)
  add ZL, r4
  adc ZH, r1
  ld r20, -Z
  ori r20, 0x01
  st Z+, r20
  ld r20, Z
  ori r20, 0x01
  st Z+, r20
  ld r20, Z
  ori r20, 0x01
  st Z, r20

  ;; Computer Paddle
  ldi ZL, lo8(frame_segment_2)
  ldi ZH, hi8(frame_segment_2)
  add ZL, r5
  adc ZH, r1
  ld r20, -Z
  ori r20, 0x80
  st Z+, r20
  ld r20, Z
  ori r20, 0x80
  st Z+, r20
  ld r20, Z
  ori r20, 0x80
  st Z, r20

  call draw_frame

  call update_player_paddle
  ; Delay
  ldi r24, 100
  call delay_ms

  call update_player_paddle
  ; Delay
  ldi r24, 100
  call delay_ms

  ;; if (x == 1) and ((y < py) or (y >= py+3)), GAME OVER! 
  mov r18, r2
  cpi r18, 1
  brne 1f
  cp r3, r4
  brsh 2f
  jmp 3f
2:
  mov r18, r4
  inc r18
  inc r18
  inc r18
  cp r3, r18 
  brlo 1f
3:
  jmp 3b
1:
  ;;

  jmp loop
  jmp main

Discussions