Full Version : Milkie & Ochoco Pong Game (AVR ASM)
avr >>GAME & VIDEO PROJECTS >>Milkie & Ochoco Pong Game (AVR ASM)


Admin3- 04-18-2006
Eric Milkie & Jomar Ochoco Pong

For our EE 476 final project, we wanted to make something that would be fun and also allow us to use many of the different embedded control techniques we have learned throughout the semester. We thought a game would be a perfect example. After considering some other games, we chose Pong. We felt that there would be enough graphics to make an interesting looking game, but still does not require complicated graphics algorithms, which would be difficult to implement on an LCD and relatively slow processor.

Project description:

We used an Atmel AT90S8535 microcontroller for this project. We used the ADC on the chip to read the positions of the potentiometer controllers (see Hardware). The game is for two player simultaneous play, although we found it is also challenging and fun to play against yourself using both controllers.

Link: http://instruct1.cit.cornell.edu/courses/e...ilkie/pong.html

CODE


;********************************MACROS***********************************
; PORTB is control lines in following order
; NC  NC  NC  NC /CE WR RD C/D
; PORTC is data
; DDR* = 0 ==> input pin
; when used to read status, doesn't matter if pull up is active or not
;checks the status of the LCD display
;takes as input what a valid status is
.MACRO statusi
; ldi temp2, 0b01010101
; out PORTB, temp2
clr  temp  ;set PORTC to all inputs
out DDRC, temp  
; ser temp
; out PORTC, temp ;set pull ups, why the hell not???
statuswait:
ldi temp, 0b00010101
out  PORTB, temp ;set control lines
in temp, PINC ;read data
nop
nop
andi temp, @0
ldi temp1, 0b00011101
out PORTB, temp1 ;set control lines
cpi temp, @0 ;compare
brne statuswait ;if status check fails, try again
ldi temp, 0b00011010;return chip to read status to avoid double writing (VERY bad)
out PORTB, temp
.ENDMACRO

;checks the status of the LCD display
;takes as input what a valid status is
.MACRO status
; ldi temp2, 0b01010101
; out PORTB, temp2
clr  temp  ;set PORTC to all inputs
out DDRC, temp  
; ser temp
; out PORTC, temp ;set pull ups, why the hell not???
statuswait:
ldi temp, 0b00010101
out  PORTB, temp ;set control lines
in temp, PINC ;read data
nop
nop
and temp, @0
ldi temp1, 0b00011101
out PORTB, temp1 ;set control lines
cp temp, @0 ;compare
brne statuswait ;if status check fails, try again
ldi temp, 0b00011010;return chip to read status to avoid double writing (VERY bad)
out PORTB, temp
.ENDMACRO
 
;writes data to the LCD display
;takes as input the data to be written
.MACRO writei
ser temp  ;set PORTC to all outputs
out DDRC, temp  
ldi temp, @0  
out  PORTC, temp ;put data on PORTC
ldi temp, 0b00010010
out PORTB, temp ;set control lines
ldi temp, 0b00011010
out PORTB, temp ;bring /CE back up
.ENDMACRO
;writes data to the LCD display
;takes as input the data to be written
.MACRO write
ser temp  ;set PORTC to all outputs
out DDRC, temp  
out  PORTC, @0 ;put data on PORTC
ldi temp, 0b00010010
out PORTB, temp ;set control lines
ldi temp, 0b00011010
out PORTB, temp ;bring /CE back up
.ENDMACRO

;writes a command to LCD display
;takes as input the command to be written
.MACRO commandi
ser temp  ;set PORTC to all outputs
out DDRC, temp  
ldi temp, @0  
out  PORTC, temp ;put command on PORTC
ldi temp, 0b00010011
out PORTB, temp ;set control lines
ldi temp, 0b00011011
out PORTB, temp;pulse /CE back up
.ENDMACRO
;writes a command to LCD display
;takes as input the command to be written
.MACRO command
ser temp  ;set PORTC to all outputs
out DDRC, temp  
out  PORTC, @0 ;put command on PORTC
ldi temp, 0b00010011
out PORTB, temp ;set control lines
ldi temp, 0b00011011
out PORTB, temp;pulse /CE back up
.ENDMACRO

;***********************************16 bit math**********************************************
;adds two 16 bit numbers, takes in add1h, add1l, add2h, add2l
.MACRO add16  
add @1,@3 ;Add low bytes
adc @0,@2 ;Add high bytes with carry
.ENDMACRO
;compares two 16 bit numbers, takes in cp1h, cp1l, cp2h, cp2l
.MACRO  cp16
cp @1,@3 ;Compare low byte
cpc @0,@2 ;Compare high byte with carry from
  ;previous operation
.ENDMACRO
;add a 16 bit number to a 16 bit immediate, takes in addh, addl, addi
.MACRO  addi16
subi @1, low(-@2) ;Add low byte ( x -(-y)) = x + y
sbci @0, high(-@2);Add high byte with carry
.ENDMACRO
;compares a 16 bit number with an immediate, takes in cp1h, cp1l, cpi
.MACRO  cpi16  
cpi @1, low(@2);Compare low byte
ldi temp, high(@2);
cpc @0, temp;Compare high byte
.ENDMACRO
;subtract constant from 16 bit number, takes in subh, subl, subi
.MACRO  subi16
subi @1,low(@2);Subtract low bytes
sbci @0,high(@2);Subtract high byte with carry
.ENDMACRO


;----------------------------------------------------------------------------

.include "c:\avrtools\appnotes\8535def.inc"


;.device AT90S8535; specifies to the assembler which chip we are using


.def pgmem  =r0; for reading text from memory
.def  status      =r1    ;0x000000 ::: lower mem (0) / upper mem (1) ::: erase (0) / write (1)

.def AnaLo  =r2; for reading the ADC
.def AnaHi  =r3;

.def timeout =r4; delay for slowing the game down
.def reload =r5; helper for delay in timer 0
.def save  =r6; saves SREG
.def speedctr =r7; assists in speeding up the ball



.def mc16uL =r8;multiplicand low byte
.def mc16uH =r9;multiplicand high byte
.def mp16uL =r10;multiplier low byte
.def mp16uH =r11;multiplier high byte
.def m16u0  =r10;result byte 0 (LSB)
.def m16u1  =r11;result byte 1
.def m16u2  =r12;result byte 2
.def m16u3  =r13;result byte 3 (MSB)
.def mcnt16u =r16;loop counter (temp)


.def drem24uL =r8 ; remainder
.def drem24uH =r9
.def dres24uL =r10; result
.def dres24uM =r11
.def dres24uH =r12  
.def dv24uH =r14
.def dv24uL =r15; divisor
.def dcnt24u =r16; loop counter



.def  temp       =r16 ; temporary register
.def ballx  =r17; ball position
.def bally  =r18
.def balldx =r19; ball velocity
.def balldy =r20
.def cnt  =r21; counter (all-purpose)
.def temp1  =r22; extra temps
.def temp2  =r23;
.def score0 =r24; player 0 score
.def score1 =r25; player 1 score

.def addrl  =r26; XL
.def addrh  =r27; XH
.def  paddle0 =r28; YL
.def paddle1 =r29; YH
  ; ZL
  ; ZH   used by timer 1

.equ speakerbit =7
.equ GAMEDELAY =20;20 mS game delay

.equ timer1on =0b00010001;used when compare match interrupt for timer1
.equ timer1off=0b00000001;is toggled

.equ R  =9960; multiplier for ADC measurements

.include        "c:\users\eam23_jgo2\macros.asm"

.cseg
.org $0000
       rjmp RESET     ;reset entry vector
       reti           ;IRQ0
       reti ;IRQ1
       reti ;t2 compare
       reti ;t2 ovfl
       reti ;t1 cap
       rjmp t1AMatch;timer 1 compare match A - for sound
       reti ;t1 compare b
       reti ;t1 ovfl
       rjmp t0int;t0 overflow
       reti
       reti
       reti
       reti
       reti
       reti
       reti    

RESET:
; stack pointer
       ldi     Temp, low(RAMEND)
       out     SPL, Temp
       ldi     Temp, high(RAMEND)
       out     SPH, Temp
       
      ;set up timer 0 for 1 mSec ticks  (slows down game)
ldi  temp, 3 ;prescale timer by 64
out  TCCR0, temp
ldi temp,256-62;preload timer since
mov Reload, temp
out  TCNT0, Reload;62.5 x (64x.25) microSec = 1.0 mSec.  
       
      ;set up timer 1 for compare match interrupt (plays sound)
ldi temp, timer1off
out TIMSK, temp
ldi temp, 0b00001001
out TCCR1B, temp

       
      ; port A -> analog for two controllers
       
      ;set port B for LCD control and processor communication
       ldi     temp, 0b10111111
      out     DDRB, temp
       clr     temp
       out     PORTB, temp
       
      ; port C -> data for LCD
       
       
      ; port D -> control buttons (start button), plus sound output on one pin.
       ldi     temp, 0b10000000
       out     DDRD, temp
       clr temp
       out     PORTD, temp            ;turn off pullups
       
       sei  ;Enable interrupts





      ;initialize LCD display graphics area starting at 0000h
     
; graphics home address = 0000h
   
statusi 0x03      
       writei  0x00
       statusi 0x03
       writei  0x00
       statusi 0x03
       commandi 0x42

; start next line 0x1e bytes later
       statusi 0x03
       writei  30
       statusi 0x03
       writei  0x00
       statusi 0x03
       commandi 0x43
       
;initialize LCD text area starting at 1400h
       statusi 0x03
       writei  0x00
       statusi 0x03
       writei  0x14
       statusi 0x03
       commandi 0x40

       statusi 0x03
       writei  30
       statusi 0x03
       writei  0x00
       statusi 0x03
       commandi 0x41

;set display mode to "or"
       statusi 0x03
       commandi 0x80  

;set display mode
       statusi 0x03
       commandi 0x9C
       
      ;clear display
       rcall clrallmem
       
      ; initialize variables
       ldi score0, 0
ldi score1, 0
clt ; beginning of game flag
 
; play opening music
ldi temp, low(30)
out OCR1AH, temp
ldi temp, high(30)
out OCR1AL, temp

ldi ZL,low(40)
ldi ZH,high(40)
ldi temp,timer1on
out TIMSK,temp

start1: tst ZL
brne start1

ldi temp, low(70)
out OCR1AH, temp
ldi temp, high(70)
out OCR1AL, temp

ldi ZL,low(90)
ldi ZH,high(90)
ldi temp,timer1on
out TIMSK,temp
 
start2: tst ZL
brne start2
 
ldi temp, low(30)
out OCR1AH, temp
ldi temp, high(30)
out OCR1AL, temp

ldi ZL,low(70)
ldi ZH,high(70)
ldi temp,timer1on
out TIMSK,temp
 
start3: tst ZL
brne start3
 
ldi temp, low(75)
out OCR1AH, temp
ldi temp, high(75)
out OCR1AL, temp

ldi ZL,low(50)
ldi ZH,high(50)
ldi temp,timer1on
out TIMSK,temp
 
start4: tst ZL
brne start4
 
ldi temp, low(20)
out OCR1AH, temp
ldi temp, high(20)
out OCR1AL, temp

ldi ZL,low(100)
ldi ZH,high(100)
ldi temp,timer1on
out TIMSK,temp
 
start5: tst ZL
brne start5

ldi temp, low(50)
out OCR1AH, temp
ldi temp, high(50)
out OCR1AL, temp

ldi ZL,low(60)
ldi ZH,high(60)
ldi temp,timer1on
out TIMSK,temp
start6: tst ZL
brne start6        

nextGame:

; starting ball position
ldi ballx, 120
ldi bally, 120

; initial ball speed in y direction
ldi balldy, 1

; speed increases every 4 paddle hits
ldi temp, 4
mov speedctr, temp
 
; display info on screen and wait for buttonpress
       rcall writelabels
       
gameLoop:

ldi temp, GAMEDELAY
mov timeout, temp
rcall delay    
rcall checkControl0
rcall checkControl1
rcall eraseball
rcall updatexy
rcall drawball    

rjmp gameLoop
       
       
moveto:; LCD helper subroutine
; move address pointer to location specified in addrl, addrh

clr  temp  ;set PORTC to all inputs
out DDRC, temp  
statuswait:
ldi temp, 0b00010101
out  PORTB, temp ;set control lines
in temp, PINC ;read data
nop
nop
andi temp, 3
ldi temp1, 0b00011101
out PORTB, temp1 ;set control lines
cpi temp, 3  ;compare
brne statuswait ;if status check fails, try again
ldi temp, 0b00011010;return chip to read status to avoid double writing (VERY bad)
out PORTB, temp
   
       ser temp  ;set PORTC to all outputs
out DDRC, temp  
out  PORTC, addrl ;put data on PORTC
ldi temp, 0b00010010
out PORTB, temp ;set control lines
ldi temp, 0b00011010
out PORTB, temp ;bring /CE back up

clr  temp  ;set PORTC to all inputs
out DDRC, temp  

statuswait1:
ldi temp, 0b00010101
out  PORTB, temp ;set control lines
in temp, PINC ;read data
nop
nop
andi temp, 3
ldi temp1, 0b00011101
out PORTB, temp1 ;set control lines
cpi temp, 3  ;compare
brne statuswait1 ;if status check fails, try again
ldi temp, 0b00011010;return chip to read status to avoid double writing (VERY bad)
out PORTB, temp
       
       ser temp  ;set PORTC to all outputs
out DDRC, temp  
out  PORTC, addrh ;put data on PORTC
ldi temp, 0b00010010
out PORTB, temp ;set control lines
ldi temp, 0b00011010
out PORTB, temp ;bring /CE back up

clr  temp  ;set PORTC to all inputs
out DDRC, temp  
statuswait2:
ldi temp, 0b00010101
out  PORTB, temp ;set control lines
in temp, PINC ;read data
nop
nop
andi temp, 3
ldi temp1, 0b00011101
out PORTB, temp1 ;set control lines
cpi temp, 3  ;compare
brne statuswait2 ;if status check fails, try again
ldi temp, 0b00011010;return chip to read status to avoid double writing (VERY bad)
out PORTB, temp

ser temp  ;set PORTC to all outputs
out DDRC, temp  
ldi temp, 0x24  
out  PORTC, temp ;put command on PORTC
ldi temp, 0b00010011
out PORTB, temp ;set control lines
ldi temp, 0b00011011
out PORTB, temp ;pulse /CE back up

ret

       
drawBall:
; draws the ball on the screen at its current position
ldi  addrh, 0
ldi  addrl, 30
; each graphic line is 30 bytes long

; determine y direction (what row)
; multiply bally * 30
mov  temp, bally
rcall  mpy8u

; determine x byte (right shift 3)
mov  cnt, ballx
lsr  cnt
lsr  cnt
lsr  cnt
add addrl, cnt ;Add low bytes
clr cnt
adc addrh, cnt ;Add high bytes with carry

; move address pointer to ball location
rcall  moveto
       
; set bits around location
mov  cnt, ballx
andi  cnt, 0b00000111; find out the last three bits, which tell how
  ; far over within the current byte to place the ball
cpi cnt, 0
breq drawBall0
cpi cnt, 1
breq drawBall1
cpi cnt, 2
breq drawBall2
cpi cnt, 3
breq drawBall3
cpi cnt, 4
breq drawBall4
cpi cnt, 5
breq drawBall5
cpi cnt, 6
breq drawBall6
rjmp drawBall7
drawBall1:
rjmp drawBall1_2
drawBall2:
rjmp drawBall2_2
drawBall3:
    rjmp drawBall3_2
drawBall4:
rjmp drawBall4_2
drawBall5:
rjmp drawBall5_2
drawBall6:
rjmp drawBall6_2
 
drawBall0:
ldi temp2, 0b01100000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
       adiw addrl, 30
       rcall moveto
       
       ldi temp2, 0b11110000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
adiw addrl, 30
       rcall moveto
       
ldi temp2, 0b11110000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
       adiw addrl, 30
       rcall moveto
       
ldi temp2, 0b01100000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4

       ret
     
drawBall1_2:
ldi temp2, 0b00110000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
       adiw addrl, 30
       rcall moveto
       
       ldi temp2, 0b01111000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
adiw addrl, 30
       rcall moveto
       
ldi temp2, 0b01111000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
       adiw addrl, 30
       rcall moveto
       
ldi temp2, 0b00110000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4

       ret  

drawBall2_2:

ldi temp2, 0b00011000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
       adiw addrl, 30
       rcall moveto
       
       ldi temp2, 0b00111100
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
adiw addrl, 30
       rcall moveto
       
ldi temp2, 0b00111100
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
       adiw addrl, 30
       rcall moveto
       
ldi temp2, 0b00011000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       ret
     
drawBall3_2:
ldi temp2, 0b00001100
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
       adiw addrl, 30
       rcall moveto
       
       ldi temp2, 0b00011110
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
adiw addrl, 30
       rcall moveto
       
ldi temp2, 0b00011110
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
       adiw addrl, 30
       rcall moveto
       
ldi temp2, 0b00001100
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
       ret
                   
drawBall4_2:
ldi temp2, 0b00000110
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
       adiw addrl, 30
       rcall moveto
       
       ldi temp2, 0b00001111
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
adiw addrl, 30
       rcall moveto
       
ldi temp2, 0b00001111
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
       adiw addrl, 30
       rcall moveto
       
ldi temp2, 0b00000110
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
       ret
             
drawBall5_2:
ldi temp2, 0b00000011
rcall status3
       write temp2
       rcall status3
       commandi 0xC0; C0 - bump along to next byte
                     
       adiw addrl, 30
       rcall moveto
       
       ldi temp2, 0b00000111
rcall status3
       write temp2
       rcall status3
       commandi 0xC0; C0 - bump along to next byte
       
       ldi temp2, 0b10000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4

       adiw addrl, 30
       rcall moveto
       
       ldi temp2, 0b00000111
rcall status3
       write temp2
       rcall status3
       commandi 0xC0; C0 - bump along to next byte
       
       ldi temp2, 0b10000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4      

       adiw addrl, 30
       rcall moveto
       
       ldi temp2, 0b00000011
rcall status3
       write temp2
       rcall status3
       commandi 0xC0; C0 - bump along to next byte
       
       ret

drawBall6_2:
ldi temp2, 0b00000001
rcall status3
       write temp2
       rcall status3
       commandi 0xC0; C0 - bump along to next byte
       
       ldi temp2, 0b10000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
       adiw addrl, 30
       rcall moveto
       
       ldi temp2, 0b00000011
rcall status3
       write temp2
       rcall status3
       commandi 0xC0; C0 - bump along to next byte
       
       ldi temp2, 0b11000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
       adiw addrl, 30
       rcall moveto
       
       ldi temp2, 0b00000011
rcall status3
       write temp2
       rcall status3
       commandi 0xC0; C0 - bump along to next byte
       
       ldi temp2, 0b11000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
             
       adiw addrl, 30
       rcall moveto
       
       ldi temp2, 0b00000001
rcall status3
       write temp2
       rcall status3
       commandi 0xC0; C0 - bump along to next byte
       
       ldi temp2, 0b10000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       ret

       
drawBall7:
adiw addrl, 1
       rcall moveto
       
ldi temp2, 0b11000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
       adiw addrl, 29
       rcall moveto
       
       ldi temp2, 0b00000001
rcall status3
       write temp2
       rcall status3
       commandi 0xC0; C0 - bump along to next byte
       
       ldi temp2, 0b11100000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
       
       adiw addrl, 30
       rcall moveto
       
       ldi temp2, 0b00000001
rcall status3
       write temp2
       rcall status3
       commandi 0xC0; C0 - bump along to next byte
       
       ldi temp2, 0b11100000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
                     
       adiw addrl, 31
       rcall moveto
       
       ldi temp2, 0b11000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
       ret
       
       
status3:
; gets a status from the LCD with a return code of 0x03 (ready for next command)

clr  temp  ;set PORTC to all inputs
out DDRC, temp
statuswait_status3:
ldi temp, 0b00010101
out  PORTB, temp ;set control lines
in temp, PINC ;read data
nop
nop
andi temp, 3
ldi temp1, 0b00011101
out PORTB, temp1 ;set control lines
cpi temp, 3 ;compare
brne statuswait_status3 ;if status check fails, try again
ldi temp, 0b00011010;return chip to read status to avoid double writing (VERY bad)
out PORTB, temp
ret


eraseBall:
; counterpart to drawBall, erases the ball at its current location
ldi  addrh, 0
ldi  addrl, 30
; each graphic line is 30 bytes long

; determine y direction (what row)
; multiply bally * 30
mov  temp, bally
rcall  mpy8u

; determine x byte (right shift 3)

mov  cnt, ballx
lsr  cnt
lsr  cnt
lsr cnt
add addrl, cnt ;Add low bytes
clr cnt
adc addrh, cnt ;Add high bytes with carry

; move address pointer to ball location
rcall  moveto
       
; set bits around location
mov  cnt, ballx
andi  cnt, 0b00000111; find out the last three bits, which tell how
      ; far over within the current byte to place the ball
cpi cnt,5
brge eraseballhigh
rjmp  eraseballlow
eraseballhigh:
rjmp  eraseballhigh2
eraseballlow:
clr temp2 ;write all 0's to byte
rcall  status3
       write temp2
       rcall  status3
       commandi 0xC4
       
       adiw addrl, 30
       rcall  moveto
       clr temp2 ;write all 0's to byte
rcall  status3
       write temp2
       rcall  status3
       commandi 0xC4
       
       adiw addrl, 30
       rcall  moveto
       clr temp2 ;write all 0's to byte
rcall  status3
       write temp2
       rcall  status3
       commandi 0xC4
       
       adiw addrl, 30
       rcall  moveto
       clr temp2 ;write all 0's to byte
rcall  status3
       write temp2
       rcall  status3
       commandi 0xC4
       
       ret
           
eraseballhigh2:
clr temp2
rcall  status3
       write temp2
       rcall  status3
       commandi 0xC0; C0 - bump along to next byte
       
       clr temp2
rcall  status3
       write temp2
       rcall  status3
       commandi 0xC4; C0 - bump along to next byte
       
       adiw addrl, 30
       rcall  moveto
       clr temp2
rcall  status3
       write temp2
       rcall  status3
       commandi 0xC0; C0 - bump along to next byte
       
       clr temp2
rcall  status3
       write temp2
       rcall  status3
       commandi 0xC4; C0 - bump along to next byte
       adiw addrl, 30
       rcall  moveto
       clr temp2
rcall  status3
       write temp2
       rcall  status3
       commandi 0xC0; C0 - bump along to next byte
       
       clr temp2
rcall  status3
       write temp2
       rcall  status3
       commandi 0xC4; C0 - bump along to next byte
       adiw addrl, 30
       rcall  moveto
       clr temp2
rcall  status3
       write temp2
       rcall  status3
       commandi 0xC0; C0 - bump along to next byte
       
       clr temp2
rcall  status3
       write temp2
       rcall  status3
       commandi 0xC4; C0 - bump along to next byte
       
       ret


;********************************************
;updatexy - updates ballx and bally according to balldx and balldy
; also checks for paddle hit
; also checks for wall bounce
; also checks for misses - ball fell off the end of the playing field.
; ******************************************
updatexy:

; first do y direction
add bally,balldy
cpi bally, 0
breq hit0
cpi  bally, 250; if ball fell through 0 to 255
brcc hit0
cpi bally, 124
brcc hit124
rjmp updatex
 
hit0:
;*turn on sound
       ldi temp, low(200)
out OCR1AH, temp
ldi temp, high(200)
out OCR1AL, temp

ldi ZL,low(10)
ldi ZH,high(10)
ldi temp,timer1on
out TIMSK,temp

neg bally ;just get two's comp of bally
neg balldy
rjmp updatex

hit124:
;*turn on sound
       ldi temp, low(200)
out OCR1AH, temp
ldi temp, high(200)
out OCR1AL, temp

ldi ZL,low(10)
ldi ZH,high(10)
ldi temp,timer1on
out TIMSK,temp
 
subi bally,124;find difference with 127
neg bally ;and then subtract that from 127
subi bally,-124
neg balldy

updatex:
; now update x direction

add ballx, balldx

cpi ballx, 240-8-4; check for paddle hit
brcs skipPaddle1Check; branch if ballx < 232
sbrc balldx,7
rjmp skipPaddle1Check; ensure ball direction is correct
mov temp, bally
sub temp, paddle1
cpi temp, 16; paddle is 16 pixels long
brcs hitxr

skipPaddle1Check:
cpi ballx,236;if it hits right wall, over 240
brcc p1miss


cpi ballx, 8; check for paddle hit
brcs paddle0Check

cpi ballx, 5
brcs p0miss

ret
hitxr:; hit right paddle
cpi temp, 4
brcs hitxr1
cpi temp, 12
brcs hitxr2
subi balldx, -1
rjmp  hitxr2
hitxr1: subi balldx, -1


hitxr2: subi ballx,228;find difference with 240
neg ballx ;and then subtract that from 240
subi ballx,-228

rjmp updateend


paddle0Check:
mov temp, bally
sub temp, paddle0
cpi temp, 16
brcs hitxl
ret; miss paddle, keep ball moving, no bounce

p1miss: sbrc balldx, 7; ensure ball direction is correct
rjmp p0miss
inc score0
rjmp  screenflash; flash screen, play bad noise

p0miss: sbrs balldx, 7; ensure ball direction is correct
rjmp p1miss
inc score1
rjmp screenflash; flash screen, play bad noise


hitxl:;bally is close to 0 edge
neg ballx  
subi ballx,-16

updateend:; but hit ball too
       ldi temp, low(50)
out OCR1AH, temp
ldi temp, high(50)
out OCR1AL, temp

ldi ZL,low(20)
ldi ZH,high(20)
ldi temp,timer1on
out TIMSK,temp

neg balldx
dec speedctr
breq incBalldx

ret
incBalldx:
cpi balldx, 8
breq skipIncBalldx
cpi balldx, -8
breq skipIncBalldx
sbrs balldx, 7; if negative, skip next
inc balldx
sbrc balldx, 7
dec balldx
ldi temp, 4
mov speedctr, temp
skipIncBalldx:
ret



;***********************
;clears lcd memory
clrallmem:
      ;set the address pointer to the beginning of memory
       statusi 0x03    
       writei  0x00
       statusi 0x03
       writei  0x00
       statusi 0x03
       commandi 0x24

      ;Zero out counter
       ldi     addrh,0
       ldi     addrl,0
       
      ;set up autowrite
       statusi 0x03
       commandi        0xB0

clrmemloop:
      ;inc counter
       addi16  addrh, addrl, 0x0001
       
      ;write zero to memory
       statusi 0x08
       writei  0x00

      ;check loop status
       cpi16   addrh, addrl, 0x1680
       brne    clrmemloop      

      ;return LCD controller to normal mode
       statusi 0x08
       commandi        0xB2

ret
       
checkControl0:
; checks the position of pot 0

;set up analog converter to read channel zero
       ldi     temp, 4
       out     ADMUX, temp

rcall measure_resistance

mov dres24uL, AnaLo
mov dres24uM, AnaHi
clr dres24uH

; divide by 130
ldi temp, 130
mov dv24uL, temp
clr dv24uH
 
rcall div24u
       
       rcall erasepaddle0
       mov paddle0, dres24uL
       rcall drawpaddle0
               
ret

       
checkControl1:
; checks the position of pot 1

;set up analog converter to read channel three (channel one is dead?!)
       ldi     temp, 6
       out     ADMUX, temp

rcall measure_resistance

       mov dres24uL, AnaLo
mov dres24uM, AnaHi
clr dres24uH

ldi temp, 130
mov dv24uL, temp
clr dv24uH
 
rcall  div24u
       
       rcall erasepaddle1
mov paddle1, dres24uL
       rcall drawpaddle1    
               
ret


;=============================================
;delay -  subroutine waits for time equal to value in register timeout
;the register 'timeout' should be loaded before the call


delay: tst timeout
brne delay

ret


;=============================================  
;***** Timer 0 overflow interrupt handler  
;timer 0 ISR (timer-zero overflow)
;Enters every 1.0 mSec

t0int: in save, SREG
out  TCNT0, Reload; keeps clock ticking at 1 mSec  

dec  timeout ;subtract another mSec

noteyet:out SREG, save
reti  ;back to backgound tasks  


;***********************************************************
;Timer 1 interrupt (plays sound through the speaker)
t1AMatch:;interrupt on compare match with value in OCR1A
in  save,SREG

sbic PIND, speakerbit;toggle speaker output
rjmp t1set

sbi PORTD, speakerbit
rjmp  t1dec

t1set:
cbi  PORTD, speakerbit

t1dec:
sbiw ZL,1
brne t1end
 
ldi temp,timer1off; turn off the noize once we reach 0 on the Z counter
out TIMSK,temp

t1end:
out SREG,save
reti



;  draw paddle routines

drawpaddle0:
ldi  addrh, 0
ldi  addrl, 30
; each graphic line is 30 bytes long

; determine y (what row)
; multiply
mov  temp, paddle0
rcall  mpy8u


; move address pointer to paddle location
rcall  moveto  
       
ldi  temp2, 0b00000001
rcall  status3
       write temp2
       rcall  status3
       commandi 0xC4

       adiw addrl, 30
       rcall  moveto  
       ldi  temp2, 0b00000011
rcall  status3
       write temp2
       rcall  status3
       commandi 0xC4
       adiw addrl, 30
       rcall  moveto  
       ldi  temp2, 0b00000011
rcall  status3
       write temp2
       rcall  status3
       commandi 0xC4
       adiw addrl, 30
       rcall  moveto  
       ldi  temp2, 0b00000011
rcall  status3
       write temp2
       rcall  status3
       commandi 0xC4
       adiw addrl, 30
       rcall  moveto  
       ldi  temp2, 0b00000011
rcall  status3
       write temp2
       rcall  status3
       commandi 0xC4
       adiw addrl, 30
       rcall  moveto  
       ldi  temp2, 0b00000011
rcall  status3
       write temp2
       rcall  status3
       commandi 0xC4
       adiw addrl, 30
       rcall  moveto  
       ldi  temp2, 0b00000011
rcall  status3
       write temp2
       rcall  status3
       commandi 0xC4
       adiw addrl, 30
       rcall  moveto  
       ldi  temp2, 0b00000011
rcall  status3
       write temp2
       rcall  status3
       commandi 0xC4
       adiw addrl, 30
       rcall  moveto  
       ldi  temp2, 0b00000011
rcall  status3
       write temp2
       rcall  status3
       commandi 0xC4
       adiw addrl, 30
       rcall  moveto  
       ldi  temp2, 0b00000011
rcall  status3
       write temp2
       rcall  status3
       commandi 0xC4
       adiw addrl, 30
       rcall  moveto  
       ldi  temp2, 0b00000011
rcall  status3
       write temp2
       rcall  status3
       commandi 0xC4
       adiw addrl, 30
       rcall  moveto  
       ldi  temp2, 0b00000011
rcall  status3
       write temp2
       rcall  status3
       commandi 0xC4
       adiw addrl, 30
       rcall  moveto  
       ldi  temp2, 0b00000011
rcall  status3
       write temp2
       rcall status3
       commandi 0xC4
       adiw addrl, 30
       rcall moveto  
       ldi temp2, 0b00000011
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       adiw addrl, 30
       rcall moveto  
       ldi temp2, 0b00000011
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
       adiw addrl, 30
       rcall moveto  
       ldi temp2, 0b00000001
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
       ret


drawpaddle1:
ldi  addrh, 0
ldi  addrl, 30
; each graphic line is 30 bytes long

; determine y (what row)
; multiply
mov  temp, paddle1
rcall  mpy8u

adiw addrl, 29

; move address pointer to paddle location
rcall moveto  
       
ldi temp2, 0b10000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4

       adiw addrl, 30
       rcall moveto  
       ldi temp2, 0b11000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       adiw addrl, 30
       rcall moveto  
       ldi temp2, 0b11000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       adiw addrl, 30
       rcall moveto  
       ldi temp2, 0b11000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       adiw addrl, 30
       rcall moveto  
       ldi temp2, 0b11000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       adiw addrl, 30
       rcall moveto  
       ldi temp2, 0b11000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       adiw addrl, 30
       rcall moveto  
       ldi temp2, 0b11000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       adiw addrl, 30
       rcall moveto  
       ldi temp2, 0b11000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       adiw addrl, 30
       rcall moveto  
       ldi temp2, 0b11000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       adiw addrl, 30
       rcall moveto  
       ldi temp2, 0b11000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       adiw addrl, 30
       rcall moveto  
       ldi temp2, 0b11000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       adiw addrl, 30
       rcall moveto  
       ldi temp2, 0b11000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       adiw addrl, 30
       rcall moveto  
       ldi temp2, 0b11000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       adiw addrl, 30
       rcall moveto  
       ldi temp2, 0b11000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       adiw addrl, 30
       rcall moveto  
       ldi temp2, 0b11000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
       adiw addrl, 30
       rcall moveto  
       ldi temp2, 0b10000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       
       ret


       
      ; erase paddle routines
erasepaddle0:
ldi  addrh, 0
ldi  addrl, 30
; each graphic line is 30 bytes long

; determine y (what row)
; multiply
mov  temp, paddle0
rcall  mpy8u
ldi cnt, 16
eraseloop0:
; move address pointer to paddle location
rcall moveto  
ldi temp2, 0b00000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4
       adiw addrl, 30
       
       dec cnt
       brne eraseloop0
       ret


erasepaddle1:
ldi  addrh, 0
ldi  addrl, 30
; each graphic line is 30 bytes long

; determine y (what row)
; multiply
mov  temp, paddle1
rcall  mpy8u
ldi cnt, 16
adiw addrl, 29
eraseloop1:
 
; move address pointer to paddle location
rcall moveto  
       
ldi temp2, 0b00000000
rcall status3
       write temp2
       rcall status3
       commandi 0xC4

       adiw addrl, 30
       
       dec cnt
       brne eraseloop1
       
       ret

; Helper for reading the ADC
; Code adapted from the Digital Voltmeter lab
measure_resistance:

       ldi     temp1, 0b11000101      ;start A to D conversion
       out     ADCSR, temp1

await:  in     temp, ADCSR    ;wait for A to D done
       andi    temp, 0b01000000;by checking ADSC bit
       brne    await         ;this bit is cleared by the AtoD hardware
         
       in      AnaLo, ADCL    ;read the voltage
       in      AnaHi, ADCH
                   
      ldi temp,low(1250);put 1250 = 5V into denom
      mov dv24uL,temp
      ldi temp,high(1250)
      mov dv24uH,temp      
      sub dv24uL,AnaLo ;find 1250 - Ana for resistance calculations
      sbc dv24uH,AnaHi
       
       ldi temp,low(R) ;multiplier = R
       mov mp16uL,temp
       ldi temp,high(R)
       mov mp16uH,temp
       
       mov mc16uL,AnaLo ;multiplicand = V
       mov mc16uH,AnaHi
       
       rcall mpy16u  
           
       rcall  div24u  ;RV / vcc - v -> result is in r4,5 hopefully, r7 is 0
       
       mov AnaLo,r10 ;mov result to AnaLo/Hi for printing to LCD
       mov AnaHi,r11
       
       ret

screenflash:
;** flashes the LCD after someone misses the ball
ldi cnt,3

screenflash2:

 ;set the address pointer to the beginning of memory
       statusi 0x03    
       writei  0x00
       statusi 0x03
       writei  0x00
       statusi 0x03
       commandi 0x24

      ;Zero out counter
       ldi     addrh,0
       ldi     addrl,0
       
      ;set up autowrite
       statusi 0x03
       commandi 0xB0
       
screenflashloop:


      ;inc counter
       addi16  addrh, addrl, 0x0001

; play noise        
   
out OCR1AH, addrl
out OCR1AL, addrh

ldi ZL,low(10)
ldi ZH,high(10)
ldi temp,timer1on
out TIMSK,temp
       
      ;write zero to memory
       statusi 0x08
       writei  0xFF

      ;check loop status
       cpi16   addrh, addrl, 0x1680
       brne    screenflashloop      

      ;return LCD controller to normal mode
       statusi 0x08
       commandi        0xB2
       
ldi temp, 100
mov timeout, temp
       rcall delay
       
      ;set the address pointer to the beginning of memory
       statusi 0x03    
       writei  0x00
       statusi 0x03
       writei  0x00
       statusi 0x03
       commandi 0x24

      ;Zero out counter
       ldi     addrh,0
       ldi     addrl,0
       
      ;set up autowrite
       statusi 0x03
       commandi        0xB0

screenflashloop2:
      ;inc counter
       addi16  addrh, addrl, 0x0001
               
      ;write zero to memory
       statusi 0x08
       writei  0x00

      ;check loop status
       cpi16   addrh, addrl, 0x1680
       brne    screenflashloop2

      ;return LCD controller to normal mode
       statusi 0x08
       commandi        0xB2
       
       ldi temp, 100
       mov timeout,temp
       rcall delay
       
       dec cnt
       tst cnt
       breq screenflashend
       rjmp screenflash2
             
screenflashend:    
       rjmp nextGame
             
       
writelabels:
; Writes labels on the screen before each new game

;set pointer to begin writing
sbrc score0, 2
rjmp p0Win
sbrc score1, 2
rjmp p1Win
brtc firstgame
sbrs balldx, 7
rjmp p1msg
ldi R31, high(P0*2)
ldi R30, low(P0*2)
rjmp printMsg
p1msg:
ldi R31, high(P1*2)
ldi R30, low(P1*2)
rjmp printMsg

firstgame:
set; turn off first game flag
ldi R31, high(MSG*2)
ldi R30, low(MSG*2)

printMsg:
ldi addrl, low(0x141E)
ldi addrh, high(0x141E)

rcall status3
write  addrl
rcall status3
write  addrh
rcall status3
commandi 0x24

rcall writepgmem

; move to print scores
ldi addrl, low(0x15c2)
ldi addrh, high(0x15c2)

rcall status3
write  addrl
rcall status3
write  addrh
rcall status3
commandi 0x24

mov temp2, score0
ori temp2, 0b00010000
rcall status3
write  temp2
rcall status3
commandi 0xC0

; move to print scores
ldi addrl, low(0x15df)


Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.