;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; LED Kart 648 ; Original code by Brad Slattery 2008, ; Modifications by Adam Chevalier, April Fleck, Jerad Devries ; CSCI 381 Fall 2008, University of Wisconsin - Superior ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; LIST p=16f648a ; tell assembler what chip we are using INCLUDE "P16f648a.inc" ; include the defaults for the chip __CONFIG 0x3f18 ; sets the configuration settings (oscillator type etc.) #define debounce 8 ; debouncing constant for selecting tracks CBLOCK 0x20 ; start of general purpose registers - this is where we start defining variable names counta ; used in the delay routines countb ; used in the delay routines pc_track ; this is our track data program counter pc_end_graphics ; this is our end graphics program counter vram_1 vram_2 vram_3 vram_4 vram_5 vram_6 vram_7 vram_8 vtemp_1 ; a temporary video ram location (used when tranfering vram data to the next vram location) vtemp_2 vtemp_3 vtemp_4 vtemp_5 vtemp_6 vtemp_7 repeat_frame ; used to determine how many times we will be repeating each 'frame' car_data ; we need to know where the car is on the screen, this variable holds that data button_timer ; used to help in slowing down the button repeat rate (it prevents the car from moving many times for one button press) button_adjust ; used to help in slowing down the button repeat rate (it prevents the car from moving many times for one button press) stop_repeat ; used to help in slowing down the button repeat rate (it prevents the car from moving many times for one button press) level ; a variable to hold the level data (so we know what level we are on) speed ; we set the initial speed in the setup routine (this determines how fast the car is going) end_hold ; used to prevent us from pushing a button at the end for a specified amount of time loopCnt ; temp loop variable flashHold ; red crash flash duration temp_w, trackNo debounceOn, debounceOff ; button debouncing variables by selecting the track ENDC ; end of general purpose registers ORG 0x0000 ; org sets the origin, 0x0000 for the 16F648, movlw h'07' ; Turn comparators off movwf CMCON ; bsf STATUS, RP0 ; select bank 1 clrf TRISB ^ 0x80 ; set PORTB all outputs movlw b'11100000' ; set PORTA first three bits outputs and last four inputs movwf TRISA ^ 0x80 ; bcf STATUS, RP0 ; select bank 0 goto setup-2 ; go straight to the setup routine track_data ; selection of a track movwf temp_w movf trackNo, w addwf PCL, f nop goto first_track goto second_track goto third_track goto fourth_track first_track movf temp_w, w movf pc_track, w ; move pc_track into our working register then addwf PCL, f ; add this number to our program counter ; each time this routine is called, we will grab the next successive byte of data retlw b'11000011' ; Here's our data for track #1 retlw b'11000001' retlw b'11100001' retlw b'11100001' retlw b'11100001' retlw b'11100001' retlw b'11000001' retlw b'11000011' retlw b'11000011' retlw b'10000011' retlw b'10000111' retlw b'10000111' retlw b'10000111' retlw b'10000111' retlw b'10000011' retlw b'11000011' retlw b'11000011' retlw b'11000011' retlw b'11100001' retlw b'11110001' retlw b'11110001' retlw b'11100001' retlw b'11000011' retlw b'11000011' retlw b'11000011' retlw b'11000011' retlw b'10000111' retlw b'10001111' retlw b'10001111' retlw b'10000111' retlw b'11000011' retlw b'11000011' retlw b'11000001' retlw b'11100001' retlw b'11110001' retlw b'11111001' retlw b'11111001' retlw b'11110001' retlw b'11100001' retlw b'11000001' retlw b'10000011' retlw b'10000111' retlw b'10001111' retlw b'10011111' retlw b'10011111' retlw b'10001111' retlw b'10000111' retlw b'10000011' retlw b'11000011' retlw b'11100011' retlw b'11100111' retlw b'11000111' retlw b'11000111' retlw b'10001111' retlw b'10001111' retlw b'10001111' retlw b'10000111' retlw b'10000011' retlw b'11000001' retlw b'11110001' retlw b'11110001' retlw b'11110001' retlw b'11100001' retlw b'11000011' retlw b'11000011' retlw b'11000011' retlw b'11100001' retlw b'11110001' retlw b'11110001' retlw b'11110001' retlw b'11100011' retlw b'11000011' retlw b'10000111' retlw b'10000111' retlw b'10001111' retlw b'10011111' retlw b'10011111' retlw b'10001111' retlw b'10000111' retlw b'11000011' rlf level, 1 ; now we have made it to the next level btfsc level, 7 ; have we reached the end of the game yet? if yes then: goto collided ; goto collided routine (this will end up displaying the smiley face) decf speed, 1 ; if not, then decrement our speed variable by one (this speeds up the game) clrf pc_track retlw b'11000011' ; and return to where we came from with the first part of our track. second_track movf temp_w, w movf pc_track, w ; move pc_track into our working register then addwf PCL, f ; add this number to our program counter ; each time this routine is called, we will grab the next successive byte of data retlw b'10000001' ; Here's our data for track #2 retlw b'10000001' retlw b'11000011' retlw b'11100111' retlw b'11100111' retlw b'11000011' retlw b'10000001' retlw b'10000001' retlw b'10000001' retlw b'10011001' retlw b'10011001' retlw b'10011001' retlw b'10011001' retlw b'10000001' retlw b'10000001' retlw b'10000001' retlw b'11000011' retlw b'11100011' retlw b'11100011' retlw b'11100011' retlw b'11100011' retlw b'11100001' retlw b'11110001' retlw b'11100001' retlw b'10000001' retlw b'10000011' retlw b'10010011' retlw b'10110011' retlw b'10110011' retlw b'10110011' retlw b'10100011' retlw b'10000011' retlw b'10000111' retlw b'10001111' retlw b'10011111' retlw b'10001111' retlw b'10000001' retlw b'11000001' retlw b'11000001' retlw b'10000001' retlw b'10001001' retlw b'10011001' retlw b'10011001' retlw b'10011001' retlw b'10011001' retlw b'10001001' retlw b'10000001' retlw b'10000001' retlw b'10000001' retlw b'11000001' retlw b'11000001' retlw b'11100011' retlw b'11100011' retlw b'11000011' retlw b'10000011' retlw b'10000011' retlw b'10000111' retlw b'10001111' retlw b'10001111' retlw b'10011111' retlw b'10011111' retlw b'10001111' retlw b'10000011' retlw b'10000001' retlw b'10110001' retlw b'10111001' retlw b'10011001' retlw b'10001001' retlw b'10000001' retlw b'11000001' retlw b'11000001' retlw b'11100001' retlw b'11000001' retlw b'11000011' retlw b'11000011' retlw b'11000111' retlw b'11000111' retlw b'10000011' retlw b'10000011' retlw b'10000001' rlf level, 1 ; now we have made it to the next level btfsc level, 7 ; have we reached the end of the game yet? if yes then: goto collided ; goto collided routine (this will end up displaying the smiley face) decf speed, 1 ; if not, then decrement our speed variable by one (this speeds up the game) clrf pc_track retlw b'10000001' ; and return to where we came from with the first part of our track. ORG 0x100 third_track movlw 1 movwf PCLATH movf temp_w, w movf pc_track, w ; move pc_track into our working register then addwf PCL, f ; add this number to our program counter ; each time this routine is called, we will grab the next successive byte of data retlw b'11000111' ; Here's our data for track #3 retlw b'11000111' retlw b'10000011' retlw b'10000001' retlw b'10000001' retlw b'10100101' retlw b'10100101' retlw b'10100101' retlw b'10100101' retlw b'10100101' retlw b'10100001' retlw b'10110001' retlw b'10011001' retlw b'10000001' retlw b'10000011' retlw b'11000011' retlw b'11100111' retlw b'11100111' retlw b'11100011' retlw b'11100001' retlw b'11100001' retlw b'11000001' retlw b'10001001' retlw b'10001001' retlw b'10011001' retlw b'10011001' retlw b'10010001' retlw b'10000001' retlw b'11000001' retlw b'10000001' retlw b'10011001' retlw b'10011001' retlw b'10010001' retlw b'10110001' retlw b'10110001' retlw b'10100001' retlw b'10100001' retlw b'10000011' retlw b'10000111' retlw b'11000111' retlw b'11100111' retlw b'11000011' retlw b'11000011' retlw b'10000111' retlw b'10001111' retlw b'10001111' retlw b'10001111' retlw b'10000111' retlw b'11000001' retlw b'11100001' retlw b'11110001' retlw b'11111001' retlw b'11110001' retlw b'11110001' retlw b'11000001' retlw b'10000001' retlw b'10001001' retlw b'10011001' retlw b'10011001' retlw b'11011001' retlw b'10011001' retlw b'10001001' retlw b'10000001' retlw b'10000001' retlw b'10000001' retlw b'10000111' retlw b'10001111' retlw b'10011111' retlw b'10111111' retlw b'10111111' retlw b'10011111' retlw b'10011111' retlw b'10001111' retlw b'10000001' retlw b'10000001' retlw b'10011001' retlw b'10011001' retlw b'10000001' retlw b'10000001' retlw b'11000011' rlf level, 1 ; now we have made it to the next level btfsc level, 7 ; have we reached the end of the game yet? if yes then: goto collided ; goto collided routine (this will end up displaying the smiley face) decf speed, 1 ; if not, then decrement our speed variable by one (this speeds up the game) clrf pc_track retlw b'11000111' ; and return to where we came from with the first part of our track. fourth_track movlw 1 movwf PCLATH movf pc_track, w ; move it into our working register then addwf PCL, f ; add this number to our program counter ; each time this routine is called, we will grab the next successive byte of data retlw b'11100001' ; Here's our data for track #4 retlw b'11000001' retlw b'11000011' retlw b'10000111' retlw b'10001111' retlw b'10001111' retlw b'10011111' retlw b'10111111' retlw b'10011111' retlw b'10001111' retlw b'11000111' retlw b'11100011' retlw b'11110001' retlw b'11110001' retlw b'11111001' retlw b'11111001' retlw b'10000001' retlw b'10000001' retlw b'10000001' retlw b'10000101' retlw b'10001101' retlw b'10101101' retlw b'10101101' retlw b'10101101' retlw b'10101101' retlw b'10101001' retlw b'10001001' retlw b'10001011' retlw b'10011001' retlw b'10011001' retlw b'10011001' retlw b'10001101' retlw b'10001001' retlw b'10001001' retlw b'10001001' retlw b'11001001' retlw b'11001001' retlw b'11001001' retlw b'11000001' retlw b'11000001' retlw b'11000001' retlw b'11100011' retlw b'11100011' retlw b'11101011' retlw b'11100011' retlw b'11000001' retlw b'11000001' retlw b'11001001' retlw b'11000001' retlw b'11000001' retlw b'10000001' retlw b'10000011' retlw b'10010001' retlw b'10000001' retlw b'10000001' retlw b'10000101' retlw b'10000101' retlw b'10000001' retlw b'10000001' retlw b'10100011' retlw b'10100001' retlw b'10000001' retlw b'10000001' retlw b'10000101' retlw b'10000101' retlw b'10001101' retlw b'10011001' retlw b'10000001' retlw b'10000001' retlw b'10000001' retlw b'10110001' retlw b'10100001' retlw b'10000101' retlw b'10000001' retlw b'10000001' retlw b'10000011' retlw b'11100111' retlw b'11100011' retlw b'11100001' retlw b'11100001' rlf level, 1 ; now we have made it to the next level btfsc level, 7 ; have we reached the end of the game yet? if yes then: goto collided ; goto collided routine (this will end up displaying the smiley face) decf speed, 1 ; if not, then decrement our speed variable by one (this speeds up the game) clrf pc_track retlw '11100001' ; and return to where we came from with the first part of our track. end_data movlw 1 movwf PCLATH incf pc_end_graphics, f ; increment pc_end_graphics by one and then movf pc_end_graphics, w ; move it into our working register then addwf PCL, f ; add this number to our program counter nop ; skip one step... ; one what we have in our program counter retlw b'00011000' ; will determine which number (or graphic) we retlw b'00111000' ; draw on the screen retlw b'01111000' retlw b'00011000' retlw b'00011000' retlw b'00011000' retlw b'01111110' retlw b'01111110' ; two retlw b'00111000' ; this draws the number 2 retlw b'01111100' retlw b'11000110' retlw b'00001100' retlw b'00011000' retlw b'00110000' retlw b'01111110' retlw b'11111110' ; three retlw b'00111100' ; this draws the number 3 retlw b'01111110' retlw b'00000110' retlw b'00111110' retlw b'00111110' retlw b'00000110' retlw b'01111110' retlw b'00111100' ; four retlw b'01100110' ; this draws the number 4 retlw b'01100110' retlw b'01100110' retlw b'01100110' retlw b'01111110' retlw b'00111110' retlw b'00000110' retlw b'00000110' ; five retlw b'01111110' ; this draws the number 5 retlw b'01111110' retlw b'01100000' retlw b'01111100' retlw b'01111110' retlw b'00000110' retlw b'01111110' retlw b'01111100' ; six retlw b'00111110' ; this draws the number 6 retlw b'01111110' retlw b'01100000' retlw b'01111100' retlw b'01111110' retlw b'01100110' retlw b'01111110' retlw b'00111100' ; seven retlw b'01111111' ; this draws the number 7 retlw b'01111111' retlw b'00000011' retlw b'00000110' retlw b'00001100' retlw b'00011000' retlw b'00110000' retlw b'01100000' ; end retlw b'00111100' ; this draws a smiley face to say we have won! retlw b'01000010' retlw b'10100101' retlw b'10000001' retlw b'10100101' retlw b'10011001' retlw b'01000010' retlw b'00111100' movlw 1 movwf trackNo setup ; Okay, lets get everything setup, ready to play the game! movlw b'00001000' ; setup PORTA so that the decoder will have it's first ouput enabled movwf PORTA ; and also send out a logic 1 to the red column of led cathodes (turning them off) clrf PORTB ; we don't want any data on the screen just yet - so clear PORTB clrf vram_1 ; these next lines clear our video ram. clrf vram_2 ; if we didnt clear them, then we would get random clrf vram_3 ; dots on our screen at startup and would more than likely crash clrf vram_4 ; as soon as we started playing clrf vram_5 clrf vram_6 clrf vram_7 clrf vram_8 clrf stop_repeat ; clear all 8 bits in stop repeat (even though we only use two.) clrf pc_track ; clear pc_track (so we start from the top of this data) clrf pc_end_graphics ; clear pc_end_graphics (so we start from the top of this data) movlw b'00010000' ; set the start position of our car movwf car_data ; (almost in the middle of the screen) movlw d'12' ; set our button response delay (the higher the number, movwf button_adjust ; the longer you have to wait to be able to push the button again) movlw d'01' ; setup our level counter (start from level movwf level ; one of course...) movlw d'11' ; setup our game scrolling speed. movwf speed ; (the higher the number, the slower the scroll speed) movlw d'50' ; this prevents us from pushing a button to reset the game straight movwf end_hold ; away - which allows you to see your score beforehand movlw 1 ; initialize trackNo movwf trackNo clrf debounceOn clrf debounceOff call select_track movlw b'00001000' movwf PORTA begin ; Our main program call display ; call the display routine call fill_vram ; call the fill video ram routine goto begin ; do it all again! select_track movlw b'00001000' movwf PORTA movf trackNo, w movwf pc_end_graphics decf pc_end_graphics, f bcf STATUS, C rlf pc_end_graphics, f rlf pc_end_graphics, f rlf pc_end_graphics, f call end_data ; get 8 bits and activate column of leds 8 times movwf PORTB call delay incf PORTA, f call end_data movwf PORTB call delay incf PORTA, f call end_data movwf PORTB call delay incf PORTA, f call end_data movwf PORTB call delay incf PORTA, f call end_data movwf PORTB call delay incf PORTA, f call end_data movwf PORTB call delay incf PORTA, f call end_data movwf PORTB call delay incf PORTA, f call end_data movwf PORTB call delay btfss PORTA, 6 ; check the left button return ; start the game if pressed btfsc PORTA, 7 ; check if right button has been pressed goto rOff ; not pressed incf debounceOn, f ; update button ON state counter movlw debounce subwf debounceOn, w btfss STATUS, C ; was M button ON for debounce times? goto select_track ; NO - proceed movlw 4 ; check: trackNo == 4? subwf trackNo, w ; subtract 4 from trackNo btfsc STATUS, Z ; and if the result is 0 set trackNo = 1 clrf trackNo incf trackNo, f ; else when it's pressed, increment trackNo clrf debounceOn ; initialize counters and loop back clrf debounceOff goto select_track rOff incf debounceOff, f ; update button OFF state counter movlw debounce subwf debounceOff, w btfss STATUS, C ; was M button OFF for debounce times ? goto select_track ; NO - proceed clrf debounceOn ; YES - confirm its state clrf debounceOff goto select_track ; This next routine takes care of drawing the actual graphics on the screen. You will notice that there are eight ; "sections" here and they basically look the same. That's because they are all doing the same thing - activating a ; certain row of cathodes and then grabbing the anode data in order to turn the leds on. The only difference between ; them is that each section activates a different row of cathodes and also grabs its data to be displayed from a ; different vram location. display movf speed, w ; We need to set the speed that our game is running at, movwf repeat_frame ; so we grab that data from speed and copy it to our frame_rate loop call car ; Call the car routine (this will draw our car on the screen) movlw b'00001000' movwf PORTA movf vram_1, w ; Now we grab the first COLUMN of data from vram_1. movwf PORTB ; then we copy it to PORTB call delay ; Call the delay (to hold that one row ON for a split second) clrf PORTB movlw b'00001001' movwf PORTA movf vram_2, w ; Now we grab the first COLUMN of data from vram_2. movwf PORTB ; then we copy it to PORTB call delay ; Call the delay (to hold that one row ON for a split second) clrf PORTB movlw b'00001010' movwf PORTA movf vram_3, w ; Now we grab the first COLUMN of data from vram_3. movwf PORTB ; then we copy it to PORTB call delay ; Call the delay (to hold that one row ON for a split second) clrf PORTB movlw b'00001011' movwf PORTA movf vram_4, w ; Now we grab the first COLUMN of data from vram_4. movwf PORTB ; then we copy it to PORTB call delay ; Call the delay (to hold that one row ON for a split second) clrf PORTB movlw b'00001100' movwf PORTA movf vram_5, w ; Now we grab the first COLUMN of data from vram_5. movwf PORTB ; then we copy it to PORTB call delay ; Call the delay (to hold that one row ON for a split second) clrf PORTB movlw b'00001101' movwf PORTA movf vram_6, w ; Now we grab the first COLUMN of data from vram_6. movwf PORTB ; then we copy it to PORTB call delay ; Call the delay (to hold that one row ON for a split second) clrf PORTB movlw b'00001110' movwf PORTA movf vram_7, w ; Now we grab the first COLUMN of data from vram_7. movwf PORTB ; then we copy it to PORTB call delay ; Call the delay (to hold that one row ON for a split second) clrf PORTB movlw b'00001111' movwf PORTA movf vram_8, w ; Now we grab the first COLUMN of data from vram_8. movwf PORTB ; then we copy it to PORTB call delay ; Call the delay (to hold that one row ON for a split second) clrf PORTB btfsc stop_repeat, 1 ; Check to see if the stop repeat bit 1 has been set, call button_time ; if it has, then call the button_time routine (which will decrement the timer by one) call check_collision ; if it has not been set, then keep going here and call the check_collision routine decfsz repeat_frame, f ; then decrease repeat_frame by one, goto loop ; if its not zero then draw it all again. return ; if it is zero, then go back to where we came from... ; The key point to remember in this check_collision routine, is that if we check the Z bit in STATUS, then we are ; checking to see if our answer is ZERO or not. If the answer IS zero, then the status bit Z will be set (it will be a 1) ; this tells us 'YES THE ANSWER IS ZERO'. If the Z bit is a '0' then it is telling us 'NO, THE ANSWER IS NOT ZERO' ; So, in this next bit, we are anding two 8-bit numbers. In this case, the answer can either be '0' or a number above zero. ; we don't care exactly what number it comes to, we just want to know if the answer is zero or not. (A zero means we have not ; hit anything, while anything above zero means we have hit a wall. check_collision ; Here we are going to check if we have hit an obstacle... movf car_data, w ; Copy our car data into the w register, andwf vram_8, w ; then and our car_data with vram_8 btfsc STATUS, Z ; If the answer is NOT zero (status bit is NOT set) then - return ; otherwise, just return from where we came from... red_flash ; collision routine, makes screen flash red when you crash movlw 10 movwf flashHold movlw 8 movwf loopCnt ; display so many red lines clrf PORTA ; init row counter and switch to red color movlw 0xFF ; send all 1's to PORTB movwf PORTB call delay incf PORTA, f ; move to next row decfsz loopCnt, f ; decrement loopCnt skip if zero goto $-5 ; if not zero continue looping decfsz flashHold, f goto $-0x0A collided ; We come here if we have hit a wall or we complete the game clrf PORTB ; we dont want anything on the screen so clear PORTB movlw b'0000000' ; setup the decoder so the first column of leds is activated movwf PORTA ; and the red led cathodes are disabled (send a 1 to them) btfsc level, 0 ; check to see what level we are on, then we will add movlw d'00' ; a specified number to the pc_end_graphics variable btfsc level, 1 ; then we will end up drawing that specified number movlw d'08' ; on the screen. btfsc level, 2 movlw d'16' btfsc level, 3 movlw d'24' btfsc level, 4 movlw d'32' btfsc level, 5 movlw d'40' btfsc level, 6 movlw d'48' btfsc level, 7 movlw d'56' movwf pc_end_graphics decfsz end_hold, f ; check to see if the end_hold will allow us to reset the game goto collided_data ; if not then go straight to collided_data movlw d'01' ; if we can reset it then check both buttons movwf end_hold ; if any button is pressed then reset the game btfss PORTA, 7 ; if no button is pressed then just continue on goto setup ; to the collided_data routine btfss PORTA, 6 goto setup collided_data ; this will draw our level number or smiley face! call end_data ; grab 8-bits of data from the data table movwf PORTB ; and then place that data on PORTB call delay ; now hold that data there for a split second incf PORTA, f ; activate the next column of led cathodes call end_data ; ...repeat 8 times movwf PORTB call delay incf PORTA, f call end_data movwf PORTB call delay incf PORTA, f call end_data movwf PORTB call delay incf PORTA, f call end_data movwf PORTB call delay incf PORTA, f call end_data movwf PORTB call delay incf PORTA, f call end_data movwf PORTB call delay incf PORTA, f call end_data movwf PORTB call delay goto collided ; and do it all again car ; This routine draws the car on the screen call joystick ; First of all, call the joystick to see if we're moving. bcf PORTA, 3 ; activate the bottom row of red led cathodes (send a 0 to it) movf car_data, w ; Copy the contents of car_data to the w register, movwf PORTB ; then copy this data from w to PORTB. (so we draw the car on the screen) call delay ; call the delay - this will hold that info on the screen for a split second, bsf PORTA, 3 ; deactivate the bottom row of red led cathodes (send a 1 to it) return ; now we're finished, return to the main program joystick ; this will check our buttons btfss PORTA, 7 ; has the left button been pressed? if yes then: call go_left ; call the go_left routine, otherwise continue with the next line btfss PORTA, 6 ; has the right button been pressed? if yes then: call go_right ; call the go_right routine, otherwise continue with the next line return ; and finally, return back to the main program! go_left btfsc stop_repeat, 0 ; First we check if the stop_repeat bit is set return ; if it is set then we return to the main program rrf car_data, 1 ; If it is not set then the car will move across one space. btfsc STATUS, C ; Check if carry bit is clear, skip if it is goto red_flash ; if carry bit is set, car has gone off screen and should crash. bsf stop_repeat, 1 ; Now that we have moved one space we want to prevent our bsf stop_repeat, 0 ; car from moving another space straight away. so we set movf button_adjust, w ; the stop_repeat bits which will remain set until the movwf button_timer ; specified time period is complete. Without this, the car return ; would move way too fast for us to be able to play the game go_right btfsc stop_repeat, 0 ; as in go_left return rlf car_data, 1 btfsc STATUS, C goto red_flash bsf stop_repeat, 1 bsf stop_repeat, 0 movf button_adjust, w movwf button_timer return button_time ; This routine decrements the button_timer by one decfsz button_timer, 1 ; (we can change the value of button_timer in the setup routine) return ; If the timer has not yet reached zero, then it returns to the main program bcf stop_repeat ,0 ; If the timer has reached zero, then we clear the stop_repeat bits bcf stop_repeat, 1 ; this then allows us to press a button again return ; return to where we came from... ; This next section basically fills the video ram locations ; with the data from the previous video ram location - This is ; how we get the screen to scroll. It also grabs a new byte of ; data from the track data table to display in video ram 1. fill_vram movf vram_1, 0 ; Copy vram_1 into vtemp_1 to use as a backup movwf vtemp_1 ; storage location. (just before we overwrite vram_1) movf vram_2, 0 ; Copy vram_1 into vtemp_2 to use as a backup movwf vtemp_2 ; storage location. (just before we overwrite vram_2) movf vram_3, 0 ; Copy vram_1 into vtemp_3 to use as a backup movwf vtemp_3 ; storage location. (just before we overwrite vram_3) movf vram_4, 0 ; Copy vram_1 into vtemp_4 to use as a backup movwf vtemp_4 ; storage location. (just before we overwrite vram_4) movf vram_5, 0 ; Copy vram_1 into vtemp_5 to use as a backup movwf vtemp_5 ; storage location. (just before we overwrite vram_5) movf vram_6, 0 ; Copy vram_1 into vtemp_6 to use as a backup movwf vtemp_6 ; storage location. (just before we overwrite vram_6) movf vram_7, 0 ; Copy vram_7 into vtemp_7 to use as a backup movwf vtemp_7 ; storage location. (just before we overwrite vram_7) ; Note that we don't need to make a backup of vram_8 because there are only 8 lines on the screen. ; So after we display the 8th line, it is then shifted out of the screen. Now that we have backed ; up our old vram data, we need to copy them to the next successive vram location - this basically ; shifts everything on the screen down one space. It also grabs a brand new byte of data and copies ; it into vram_1 (which means it will be displayed at the top of the screen, before it gets shifted again) call track_data ; Call track_data routine and return with a byte of data in the w register incf pc_track, f clrf PCLATH movwf vram_1 ; then copy the new byte of data to the first vram location movf vtemp_1, 0 ; copy what was in vram_1 into vram_2 (remember how we made movwf vram_2 ; a backup of vram_1 and called it vtemp_1.) movf vtemp_2, 0 ; copy what was in vram_2 into vram_3 (remember how we made movwf vram_3 ; a backup of vram_2 and called it vtemp_2.) movf vtemp_3, 0 ; copy what was in vram_3 into vram_4 (remember how we made movwf vram_4 ; a backup of vram_3 and called it vtemp_3.) movf vtemp_4, 0 ; copy what was in vram_4 into vram_5 (remember how we made movwf vram_5 ; a backup of vram_4 and called it vtemp_4.) movf vtemp_5, 0 ; copy what was in vram_5 into vram_6 (remember how we made movwf vram_6 ; a backup of vram_5 and called it vtemp_5.) movf vtemp_6, 0 ; copy what was in vram_6 into vram_7 (remember how we made movwf vram_7 ; a backup of vram_6 and called it vtemp_6.) movf vtemp_7, 0 ; copy what was in vram_7 into vram_8 (remember how we made movwf vram_8 ; a backup of vram_7 and called it vtemp_7.) return ; Now that we're all done here, go back to our main program. delay ; Here are the delay routines movlw 3 ; You can make the delay longer by increasing the decimal value, movwf counta ; or shorter by decreasing the decimal value. movwf countb again decfsz counta, 1 goto again decfsz countb, 1 goto again ; once counta and countb have reached zero return ; it will return to the main program END ; That's it!