;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; The scroller ; ; ; ; this is made for the 8x8 display ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 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.) ;================================================================================================================================== PC equ 0x02 ; The program counter will be refered to as PC 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 vram_1 ; a video ram location vram_2 ; a video ram location vram_3 ; a video ram location vram_4 ; a video ram location vram_5 ; a video ram location vram_6 ; a video ram location vram_7 ; a video ram location vram_8 ; a video ram location vtemp_1 ; a temporary video ram location (used when tranfering vram data to the next vram location) vtemp_2 ; a temporary video ram location (used when tranfering vram data to the next vram location) vtemp_3 ; a temporary video ram location (used when tranfering vram data to the next vram location) vtemp_4 ; a temporary video ram location (used when tranfering vram data to the next vram location) vtemp_5 ; a temporary video ram location (used when tranfering vram data to the next vram location) vtemp_6 ; a temporary video ram location (used when tranfering vram data to the next vram location) vtemp_7 ; a temporary video ram location (used when tranfering vram data to the next vram location) repeat_frame ; used to determine how many times we will be repeating each 'frame' endc ; end of general purpose registers ;================================================================================================================================== org 0x0000 ; org sets the origin, 0x0000 for the 16F628, movlw h'07' ; Turn comparators off movwf CMCON ; (we just want to use the ports as digital ports) bsf STATUS, RP0 ; select bank 1 (to enable us to change the Input / Output status of our ports) movlw b'00000000' ; set PORTB all outputs (A '0' means output, A '1' means input. We can set each movwf TRISB ; We can set each bit individualy. Each port having 8-bits or 8 pins. movlw b'00100000' ; set PORTA all outputs except for bit 5. Bit 5 is an input ONLY pin. movwf TRISA ; It cannot be set to an output! bcf STATUS, RP0 ; select bank 0 goto setup ; go straight to the setup routine ;================================================================================================================================== scroll_data ; Here's our letter data! incf pc_track, f ; increment pc_track by one and then movf pc_track, w ; move it into our working register THEN addwf PC ; add this number to our program counter nop ; skip one step... ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; Draw data on matrix ; HERE IS WHERE YOU ENTER YOUR DATA TO DISPLAY ON THE 8x8 MATRIX retlw b'00000000' retlw b'00000000' retlw b'00000000' ; space before we draw the data on the Matrix retlw b'00000000' retlw b'00000000' retlw b'00000000' retlw b'00000000' ; one ; depending on what we have in our program counter retlw b'00000000' ; 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' retlw b'00000000' ; space between numbers retlw b'00000000' ; two retlw b'00011000' ; this draws the number 1 retlw b'00111100' retlw b'01000110' retlw b'00001100' retlw b'00011000' retlw b'00110000' retlw b'01111110' retlw b'01111110' retlw b'00000000' ; space between numbers retlw b'00000000' ; 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' retlw b'00000000' ; space between numbers retlw b'00000000' ; four retlw b'01100110' ; this draws the number 4 retlw b'01100110' retlw b'01100110' retlw b'01111110' retlw b'01111110' retlw b'00000110' retlw b'00000110' retlw b'00000110' retlw b'00000000' ; space between numbers retlw b'00000000' ; 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' retlw b'00000000' ; space between numbers retlw b'00000000' ; six retlw b'00111100' ; 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' retlw b'00000000' ; space between numbers retlw b'00000000' ; seven retlw b'01111110' ; this draws the number 7 retlw b'01111110' retlw b'00000110' retlw b'00000110' retlw b'00001100' retlw b'00011000' retlw b'00110000' retlw b'01100000' retlw b'00000000' ; space between numbers retlw b'00000000' ; eight retlw b'00011000' retlw b'00111100' ; this draws the number 8 retlw b'01100110' retlw b'01100110' retlw b'00111100' retlw b'01100110' retlw b'01100110' retlw b'00111100' retlw b'00011000' retlw b'00000000' ; space between numbers retlw b'00000000' ; nine retlw b'00111100' ; this draws the number 9 retlw b'01111110' retlw b'01100110' retlw b'01111110' retlw b'00111110' retlw b'00000110' retlw b'01111110' retlw b'00111100' ;scolls off the screen retlw b'00000000' ; space at end retlw b'00000000' retlw b'00000000' retlw b'00000000' retlw b'00000000' retlw b'00000000' retlw b'00000000' retlw b'00000000' ; END OF DATA ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ;================================================================================================================================== setup ; Okay, lets get everything setup, ready to play! movlw b'00000000' ; setup PORTA so that the 7442 ports are all ground inputs. movwf PORTA ; and also send out a logic 1 to the red column of led cathodes (so they wont turn on) clrf PORTB ; we dont 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! (experiment with not clrf vram_5 ; clearing all these vrams and see what happens!) clrf vram_6 ; .... clrf vram_7 ; .... clrf vram_8 ; .... clrf pc_track ; clear pc_track (so we start from the top of this data begin ; the main program! call display ; call the display routine call fill_vram ; call the fill video ram routine goto begin ; do it all again! ;================================================================================================================================== ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; The next routine basically takes care of drawing the actual ; ; graphics on the screen. You will notice that there are eight ; ; "sections" here'. they basically look the same except for ; ; minor differences. Thats 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 it's data to be ; ; displayed from a different vram location. ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; display movlw d'25' ; We need to set the speed that we are scrolling at, movwf repeat_frame ; so we grab that data from speed and copy it to our frame_rate loop movlw b'00000111' 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'00000110' movwf PORTA movf vram_2, 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'00000101' movwf PORTA movf vram_3, 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'00000100' movwf PORTA movf vram_4, 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'00000011' movwf PORTA movf vram_5, 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'00000010' movwf PORTA movf vram_6, 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'00000001' movwf PORTA movf vram_7, 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'00000000' movwf PORTA movf vram_8, 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 decfsz repeat_frame ; 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... ;================================================================================================================================== ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; 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) ;================================================================================================================================== ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; Did you notice that we don't need to make a backup of vram_8? ; ; That's 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 then 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 scroll_data ; Call scroll_data routine and return with a byte of data in the w register 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. ;================================================================================================================================== ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; Heres the delay routines! ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; delay ; This first delay is a rather fast one. movlw d'02' ; You can make the delay longer by #### the higher the value, the more the matrix will flicker #### movwf counta ; increasing the decimal value. Or you movwf countb ; can make the delay shorter by decreasing again decfsz counta, 1 ; the decimal value. 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!