Only Source Code of Project
Only Source Code of Project
MP CEP/ASSIGNMENT 4
Submitted By:
Nauman Masood FA19-BEE-047
Danyal Nasir FA19-BEE-118
MuhammadTouseef FA19-BEE-107
Usama Arif FA19-BEE-007
Supervisor:
“Dr. Omer Chughtai”
RS EQU P1.7
EN EQU P1.6
DISPLAY_PORT EQU P0
VCC EQU P2
GND EQU P3
KEYPAD_PORT EQU P1
REG_6 EQU 06
REG_5 EQU 05
REG_4 EQU 04
REG_3 EQU 03
REG_2 EQU 02
REG_1 EQU 01
REG_0 EQU 00
TEMP EQU 28H
STEMP EQU 29H
INITIAL_LENGTH_SNAKE EQU 2D
INITIAL_SNAKE_DIR EQU 2D
; 0 - up
; 1 - right
; 2 - down
; 3 - left
MAIN
: ACALL _setup
loop:
MOV CURR_KEY_STATES, KEYPAD_PORT
LCALL _get_input_update_new_direction
ACALL _clear_display_buffer
ACALL _set_snake
ACALL
_place_snake_egg
ACALL _update_head
ACALL _check_if_head_coincides_with_egg
ACALL _update_snake_array
ACALL _check_if_snake_ate_itself
JZ over
ACALL _write_score_to_lcd
ACALL _display
SJMP loop
over:
MOV R7, #08H
show_dead_again:
ACALL _display
ACALL _delay
DJNZ R7, show_dead_again
ACALL _delay
MOV VCC, #00H
MOV GND, #00H
ACALL _game_over_message
check_again_end:
MOV CURR_KEY_STATES, KEYPAD_PORT
MOV A, #ANY_KEY_MASK
ACALL A_detect_key_press
JZ check_again_end
SJMP MAIN
_clear_display_buffer:
MOV R2, #8
MOV R0, #DISP_START_ADDR
start:
MOV @R0, #00H
INC R0
DJNZ R2, start
RET
_setup:
MOV GAME_OVER, #0FFH
MOV SCORE, #0
MOV KEYPAD_PORT, #0FFH
ACALL _clear_display_buffer
ACALL lcd_init
ACALL _welcome_message
check_again:
MOV CURR_KEY_STATES, KEYPAD_PORT
MOV A, #ANY_KEY_MASK
ACALL A_detect_key_press
JZ check_again
ACALL lcd_init
MOV DPTR, #SCORE_MESSAGE
ACALL _display_string_on_lcd
_set_snake:
MOV R0, #SNAKE_LENGTH_PTR
MOV A, @R0
MOV R3, A
_update_head:
MOV A, #SNAKE_TAIL
ADD A, SNAKE_LENGTH_PTR
DEC A
MOV R0, A
MOV A, @R0
up_left:
ACALL _update_left
; update the current direction
MOV SNAKE_DIR, SNAKE_NEXT_DIR
AJMP next_update
AJMP next_update
left:
CJNE R7,#3,next_update
; direction is left
; X++
MOV R6, SNAKE_NEXT_DIR
left_up: CJNE R6, #0, left_right
ACALL _update_up
; update the current direction
; update the current direction
MOV SNAKE_DIR, SNAKE_NEXT_DIR
AJMP next_update
next_update:
MOV STEMP, A
RET
_update_snake_array:
MOV A, #SNAKE_TAIL
ADD A, SNAKE_LENGTH_PTR
DEC A
MOV R0, A
MOV @R0, STEMP ; write the new head value back to head location -
egg logic later
next_mem_loc:
DEC R0
MOV STEMP, @R0
MOV @R0, TEMP
MOV TEMP, STEMP
CJNE R0, #SNAKE_TAIL, next_mem_loc
RET
_display:
MOV R6, #22H ; this value controls the speed of the snake
again_2:
MOV R2, #8
MOV R3, #01H
MOV R0, #DISP_START_ADDR
again:
MOV A, @R0
INC R0
CPL A
MOV GND, A
MOV VCC, R3
MOV A, R3
RL A
MOV R3, A
ACALL _delay_between_frame
; Function: _update_right
; Description: X--
_update_right:
PUSH REG_6
PUSH 0E0H
ANL A, #0FH
JZ add_7
DEC A
SJMP dont_add
add_7:
ADD A, #7D
dont_add:
MOV R6, A
POP 0E0H
ANL A, #0F0H
ORL A, R6
POP REG_6
RET
; Function: _update_up
; Description: Y--
_update_up:
PUSH REG_6
PUSH 0E0H
ANL A, #0F0H
SWAP A
JZ add_right
DEC A
SJMP dont_add_right
add_right:
ADD A, #7
dont_add_right:
SWAP A
MOV R6, A
POP 0E0H
ANL A, #0FH
ORL A, R6
POP REG_6
RET
; Function: _update_left
; Descsription: X++
_update_left:
PUSH REG_6
PUSH 0E0H
ANL A, #0FH
CJNE A, #07, dont_subtract
CLR A
SJMP dont_increment
dont_subtract:
INC A
dont_increment:
MOV R6,A
POP 0E0H
ANL A, #0F0H
ORL A, R6
POP REG_6
RET
; Function: _update_down
; Description: Y++
_update_down:
PUSH REG_6
PUSH 0E0H
ANL A, #0F0H
SWAP A
CJNE A, #07, dont_subtract_left
CLR A
SJMP dont_increment_left
dont_subtract_left:
INC A
dont_increment_left:
SWAP A
MOV R6, A
POP 0E0H
ANL A, #0FH
ORL A, R6
POP REG_6
RET
; Function: _convert_and_set_bit
; Arguments: A
; Description: Get the XY coordinate in A and set the corresponding bit
_convert_and_set_bit:
PUSH 0E0H
ANL A, #0FH
MOV B, #DISP_START_ADDR
ADD A, B
MOV R0, A
POP 0E0H
SWAP A
ANL A, #0FH
MOV R3, A
MOV A, #01H
back_up:
RL A
DJNZ R3, back_up
input_up:
MOV A, #KEY_MASK_1
LCALL A_detect_key_press
JZ input_left
MOV SNAKE_NEXT_DIR, #1
RET
input_left:
MOV A, #KEY_MASK_2
LCALL A_detect_key_press
JZ input_down
MOV SNAKE_NEXT_DIR, #2
RET
input_down:
MOV A, #KEY_MASK_3
LCALL A_detect_key_press
JZ return_get_input_new_direction
MOV SNAKE_NEXT_DIR, #3
return_get_input_new_direction: RET
; Function: A_detect_key_press
; Description: Returns True in A if key is pressed
A_detect_key_press:
; Save the current context on the stack
PUSH REG_0
PUSH PSW
MOV R0, A
MOV A, CURR_KEY_STATES
CPL A
ANL A, R0
; Function: _check_if_head_coincides_with_egg
; Description: This function checks if the snake has eaten the egg or not
_check_if_head_coincides_with_egg:
MOV DPTR, #EGG_LOCATIONS
MOV A, SCORE
MOVC A, @A+DPTR
MOV R4, A
MOV A, #SNAKE_TAIL
ADD A, SNAKE_LENGTH_PTR
DEC A
MOV R0, A
MOV A, @R0
XRL A, R4
JNZ return_check_if_head
INC SCORE
INC SNAKE_LENGTH_PTR
return_check_if_head: RET
; Function: _place_snake_egg
; Description: Place the snake egg. Right now it is according to a fixed table of
locations,
; further improvements can make it random
_place_snake_egg:
MOV DPTR, #EGG_LOCATIONS
MOV A, SCORE
MOVC A, @A+DPTR
ACALL _convert_and_set_bit
RET
; Function: _check_if_snake_ate_itself
; Description: The function checks if the snake ate itself or not
_check_if_snake_ate_itself:
MOV A, #SNAKE_TAIL
ADD A, SNAKE_LENGTH_PTR
DEC A
MOV R0, A
MOV TEMP, @R0
not_equal:
DEC R0
MOV A, @R0
XRL A, TEMP
JZ its_game_over
CJNE R0, #SNAKE_TAIL, not_equal
RET
its_game_over:
MOV GAME_OVER, #00H
RET
; Function: _delay_between_frame
; Description: Used for delay between each frame of display
_delay_between_frame:
PUSH REG_4
PUSH REG_3
PUSH REG_2
MOV R4,#05H
WAIT1: MOV R3,#20H
WAIT2: MOV R2,#01H
WAIT3: DJNZ R2,WAIT3
DJNZ R3,WAIT2
DJNZ R4,WAIT1
POP REG_2
POP REG_3
POP REG_4
RET
_delay:
PUSH REG_4
PUSH REG_3
PUSH REG_2
MOV R4,#01H
WAIT_1: MOV R3,#60H
WAIT_2: MOV R2,#00H
WAIT_3: DJNZ R2,WAIT_3
DJNZ R3,WAIT_2
DJNZ R4,WAIT_1
POP REG_2
POP REG_3
POP REG_4
RET
_delay_long:
PUSH REG_4
PUSH REG_3
PUSH REG_2
MOV R4,#05H
WAIT_1_long: MOV R3,#00H
WAIT_2_long: MOV R2,#00H
WAIT_3_long: DJNZ R2,WAIT_3_long
DJNZ R3,WAIT_2_long
DJNZ R4,WAIT_1_long
POP REG_2
POP REG_3
POP REG_4
RET
lcd_init:
MOV A, #38H
ACALL lcd_cmd
ACALL _delay_between_frame
MOV A, #0EH
ACALL lcd_cmd
ACALL _delay_between_frame
MOV A, #01H
ACALL lcd_cmd
ACALL _delay_between_frame
MOV A, #80H
ACALL lcd_cmd
ACALL _delay_between_frame
RET
lcd_cmd:
MOV DISPLAY_PORT, A
CLR RS
SETB EN
MOV R4,#05H
delay: DJNZ R4, delay
CLR EN
RET
lcd_data:
MOV DISPLAY_PORT, A
SETB RS
SETB EN
MOV R4,#05H
delay_data: DJNZ R4, delay_data
CLR EN
RET
_write_score_to_lcd:
MOV A, SCORE
CJNE A, #0AH, check_more_than_ten
check_more_than_ten: JNC convert_number
ADD A, #30H
MOV DISPLAY_PORT, A
ACALL lcd_data
sjmp reset_to_original_pos
convert_number:
MOV B, #0AH
DIV AB
ADD A, #30H
MOV DISPLAY_PORT, A
ACALL lcd_data
ACALL _delay_between_frame
MOV A, B
ADD A, #30H
MOV DISPLAY_PORT, A
ACALL lcd_data
reset_to_original_pos:
ACALL _delay_between_frame
MOV A, #87H
ACALL lcd_cmd
ACALL _delay_between_frame
RET
_welcome_message:
MOV DPTR, #WELCOME_MESSAGE
ACALL _display_string_on_lcd
MOV A, #0C0H
ACALL lcd_cmd
ACALL _delay_between_frame
ACALL _delay_long
RET
_game_over_message:
MOV A, #0C0H
ACALL lcd_cmd
ACALL _delay_between_frame
ACALL _delay_long
RET
_display_string_on_lcd:
; takes input as DPTR
CLR A
next_character:
CLR A
MOVC A,@A+DPTR
JZ exit
INC DPTR
ACALL lcd_data
ACALL _delay_between_frame
SJMP next_character
exit:
RET
ORG 0800H
EGG_LOCATIONS: DB 43H, 23H, 15H, 67H, 50H, 33H, 47H, 03H, 25H, 15H,
26H, 52H, 77H, 27H, 56H, 64H, 32H, 55H, 38H, 13H, 11H, 17H, 43H, 23H, 15H,
67H, 50H, 33H, 47H, 03H, 25H, 15H, 26H, 52H, 77H, 27H, 56H, 64H, 32H, 55H,
38H, 13H, 11H, 17H
WELCOME_MESSAGE: DB "SNAKE GAME!",0
PRESS_KEY: DB "PRESS TO START",0
END_MESSAGE: DB "GAME OVER!", 0
SCORE_MESSAGE: DB "SCORE: ", 0
END