- ###################################################################
- # CS232 MP 4
- #
- # To help you debug, I have added a "globl" label called exception.
- # When you test your code, add exception as a breadkpoint, and your
- # code will stop as soon as an exception is encountered. You can
- # then step through the code until you finc the error.
- ###################################################################
- .data
- chunkIH : .space 16 # save space for four registers
- buffer : .space 32768
- tokenxy : .space 1600 # space for 200 possible (x, y) values
- mystate : .word 0
- scandone: .word 0
- .text
- #### Start of main ####
- main:
- # Step 0: Enable the necessary interrupts
- li $t0, 0xb001 # enable bonk, scan and timer interrupts
- mtc0 $t0, $12 # set Status register
- #li $t7, 0
- # Step 1: Start a new scan
- main_start_scan:
- lw $t0, 0xffff0020($0) # get current x-coordinate
- sw $t0, 0xffff0050($0) # set as scan-x location
- lw $t0, 0xffff0024($0) # get current y-coordinate
- sw $t0, 0xffff0054($0) # set as scan-x location
- la $t8, buffer # get buffer address
- sw $t8, 0xffff0058($0) # start scan
- # Step 2: Wait for scan to terminate
- #bne $t7, $0, no_wait
- sw $0, scandone
- #addi $t7, $t7, 1
- main_wait:
- lw $t0, scandone
- beq $t0, $0, main_wait
- no_wait:
- # Step 3: Compute pointer to root node (MP3b)
- li $t3, 0 # cumulative XOR
- move $t4, $t8
- addi $a1, $t4, 32768
- main_loop:
- lw $a0, 0($t4) # get data
- jal isEvenGraycode # check if this node is even
- lw $t5, 4($t4)
- xor $t3, $t3, $t4
- xor $t3, $t3, $t5
- main_skip:
- addi $t4, $t4, 8 # move on to next node
- bne $a1, $t4, main_loop
- main_loop_done: # v0 points to root node
- # Step 4: Drive to token location (hopefully!)
- move $v0, $t3
- lw $a0, 0($v0) # a0 = root->data
- addi $sp, $sp, -4
- sw $ra, 0($sp)
- jal getCoords
- lw $ra, 0($sp)
- addi $sp, $sp, 4
- la $t6, tokenxy # base address of tokenxy array
- sw $v0, 0($t6) # save x-coord
- sw $v1, 4($t6) # save y-coord
- sw $0, mystate
- lw $t0, 0xffff001c($0) # start timer
- addi $t0, $t0, 100
- sw $t0, 0xffff001c($0)
- j main_start_scan
- main_state_0:
- lw $t0, mystate
- beq $t0, $0, main_state_0
- li $t1, 1
- main_state_1:
- lw $t0, mystate
- beq $t0, $t1, main_state_1
- j main_start_scan # now go for the next token
- jr $ra # Should never get here!
- #### End of main ####
- #### Start of helper functions ####
- isEvenGraycode: # a0 = integer to check
- srl $t1, $a0, 16 # shift right logical, not arithmetic!
- xor $t0, $a0, $t1
- srl $t1, $t0, 8
- xor $t0, $t0, $t1
- srl $t1, $t0, 4
- xor $t0, $t0, $t1
- srl $t1, $t0, 2
- xor $t0, $t0, $t1
- srl $t1, $t0, 1
- xor $t0, $t0, $t1 # t0 = graycodeToBinary(a0)
- andi $v0, $t0, 1 # v0 = 1 iff t0 is odd
- xori $v0, $v0, 1 # flip the bit
- beq $v0, $0, main_skip
- jr $ra
- getCoords: # a0 = integer data
- srl $t1, $a0, 16 # shift right logical, not arithmetic!
- xor $t0, $a0, $t1
- srl $t1, $t0, 8
- xor $t0, $t0, $t1
- srl $t1, $t0, 4
- xor $t0, $t0, $t1
- srl $t1, $t0, 2
- xor $t0, $t0, $t1
- srl $t1, $t0, 1
- xor $t0, $t0, $t1 # t0 = graycodeToBinary(a0)
- sra $t0, $t0, 1 # t0 = 256x + y
- andi $v1, $t0, 0xFF # v1 = t0 mod 256 = y
- srl $v0, $t0, 8 # v0 = t0 / 256 = x
- jr $ra
- #### End of helper functions ####
- #### Kernel section ####
- .ktext 0x80000080
- interrupt_handler:
- .set noat
- move $k1, $at # save $at
- .set at
- la $k0, chunkIH
- sw $t0, 0($k0) # save registers
- sw $t1, 4($k0)
- sw $a0, 8($k0)
- sw $a1, 12($k0)
- mfc0 $t0, $13 # get Cause register
- srl $t1, $t0, 2
- andi $t1, $t1, 0xF # examine exception code field
- bne $t1, 0, exception # if its non-zero, it is an exception
- # Now examine the kind of interrupt we have
- andi $t1, $t0, 0x1000 # is this a bonk interrupt?
- bne $t1, $0, bonk_interrupt
- andi $t1, $t0, 0x2000 # is this a scan interrupt?
- bne $t1, $0, scan_interrupt
- andi $t1, $t0, 0x8000 # is this a timer interrupt?
- bne $t1, $0, timer_interrupt
- j int_done # unknown interrupt
- bonk_interrupt:
- sw $0, 0xffff0060($0) # acknowledge bonk interrupt
- # We should not get a bonk. If we do, we must be chasing a bad token
- li $t0, 2
- sw $t0, mystate # ignore this "token"!
- j int_done
- scan_interrupt:
- sw $0, 0xffff0064($0) # acknowledge scan interrupt
- li $t0, 1 # set scandone = 1 to quit main_wait loop
- sw $t0, scandone
- j int_done
- timer_interrupt:
- sw $0, 0xffff006c($0) # acknowledge timer interrupt
- la $a0, tokenxy
- #move $a0, $s0
- #beq $a0, $t6, int_done
- lw $t0, mystate
- bne $t0, $0, move_along_y
- lw $a0, 0($a0)
- lw $t0, 0xffff0020($0) # t0 = spimbot_get_x()
- sub $t0, $a0, $t0 # t0 = diff
- abs $t1, $t0 # t1 = abs(diff)
- bge $t1, 2, x_else
- li $t0, 1
- sw $t0, mystate
- j move_along_y
- x_else:
- ble $t0, $0, x_180
- sw $0, 0xffff0014($0)
- li $t0, 1
- sw $t0, 0xffff0018($0)
- j x_set_timer
- x_180:
- li $t0, 180
- sw $t0, 0xffff0014($0)
- li $t0, 1
- sw $t0, 0xffff0018($0)
- x_set_timer:
- li $t0, 10
- mul $t1, $t1, 10
- lw $t0, 0xffff001c($0)
- add $t0, $t0, $t1
- sw $t0, 0xffff001c($0)
- li $t0, 10
- sw $t0, 0xffff0010($0)
- move_along_y:
- lw $t0, mystate
- bne $t0, 1, int_done
- la $a1, tokenxy
- #move $a1, $s0
- lw $a1, 4($a1)
- lw $t0, 0xffff0024($0) # t0 = spimbot_get_y()
- sub $t0, $a1, $t0 # t0 = diff
- abs $t1, $t0 # t1 = abs(diff)
- bge $t1, 2, y_else
- li $t0, 2
- sw $t0, mystate
- sw $0, 0xffff0010($0) # stop driving!
- #addi $s0, $s0, 8
- j int_done
- y_else:
- ble $t0, $0, y_270
- li $t0, 90
- sw $t0, 0xffff0014($0)
- li $t0, 1
- sw $t0, 0xffff0018($0)
- j y_set_timer
- y_270:
- li $t0, 270
- sw $t0, 0xffff0014($0)
- li $t0, 1
- sw $t0, 0xffff0018($0)
- y_set_timer:
- li $t0, 10
- mul $t1, $t1, 100
- lw $t0, 0xffff001c($0)
- add $t0, $t0, $t1
- sw $t0, 0xffff001c($0)
- li $t0, 10
- sw $t0, 0xffff0010($0)
- int_done:
- la $k0, chunkIH
- lw $t0, 0($k0) # restore registers
- lw $t1, 4($k0)
- lw $a0, 8($k0)
- lw $a1, 12($k0)
- .set noat
- move $at, $k1 # restore $at
- .set at
- mfc0 $k0, $14 # EPC
- rfe # return from exception handler
- jr $k0
- #### Global exception label ####
- .globl exception
- exception:
- j int_done
- #### End of program ####
