After thinking about the assignment awhile I realized that I don't have to refresh all eight columns of the display as I did in homework assignment #1. All I really had to do was display a single dot at a certain column and row position for some length of time before going on to the next dot. Since both column and row position can be represented by a three bit value (0 through 7), I realized I could easily represent any particular dot location on the display as a single packed BCD byte with the row value in the high nibble and the column value in the low nibble. For example, a packed BCD value of 0x70 would be used to represent the top right dot on the display at row 7 and column 0.
I built a table to hold the packed BCD dot position for all twenty eight dots that occupy the outer edge positions on the display. The table was ordered so that the first table entry is the top left dot position on the display, with subsequent entries containing dot positions that sequentially move the dot in a clock-wise direction around the display. The last table entry is actually a group of instructions that reset the 16 bit table pointer and wrap-around to the beginning of the table.
The main program loop was designed to read a dot position byte from the table, then uses the 'column' nibble in that byte to set the 7442 address and select the column, then converts the 'row' nibble in that byte to a bit mask which, once written to PORTB, will display the dot. The dot is displayed for 250 msecs before repeating the loop to display the next dot.
The program uses 74 words of program memory and 5 bytes of RAM. As with my homework #1 example, this example for the homework #2 assignment uses techniques that may not be very intuitive for beginning programmers, and I apologize for that. Please don't be afraid to ask questions...
Cheerful regards, Mike
Code: Select all
;******************************************************************
; Homework #2: 8x8 Dot Animation Mike McLaren, 05-Jan-2013 *
;******************************************************************
include "P16f648a.inc"
__config _WDT_OFF&_LVP_OFF&_MCLRE_OFF&_BOREN_OFF&_INTOSC_OSC_NOCLKOUT
list st=off ; turn symbol table off in LST file
errorlevel -302 ; disable bank warning messages
radix dec ; use decimal numbers
;
; variables
;
cblock 0x20
ptrl ; table pointer
ptrh ; "
work ; ndx2mask subroutine work variable
mask ; "
delayhi ; delay subroutine variable
endc
;******************************************************************
; main init *
;******************************************************************
org 0x000
init
clrf STATUS ; bank 0 |B0
movlw 0x07 ; |B0
movwf CMCON ; comparator off, digital I/O |B0
bsf STATUS,RP0 ; bank 1 |B1
clrf TRISA ; porta all outputs, except RA5 |B1
clrf TRISB ; portb all outputs |B1
bcf STATUS,RP0 ; bank 0 |B0
call tblprep ; init table pointer |B0
;******************************************************************
; main loop *
;******************************************************************
loop
clrf PORTB ; blank the display |B0
call rdtable ; get packed BCD 'row' & 'col' |B0
movwf PORTA ; set 7442 addr (select column) |B0
call ndx2mask ; convert 'row' index to a mask |B0
movwf PORTB ; display the dot |B0
call delay ; delay 250 msecs |B0
incf ptrl,F ; bump table ptr |B0
skpnz ; " |B0
incf ptrh,F ; " |B0
goto loop ; branch (loop forever) |B0
;******************************************************************
rdtable
movf ptrh,W ; |B0
movwf PCLATH ; |B0
movf ptrl,W ; |B0
movwf PCL ; |B0
;******************************************************************
ndx2mask
movwf work ; save (use upper nibble 'row') |B0
movlw b'00000100' ; ndx 2 |B0
btfss work,1+4 ; bit 1 set? no, skip, else |B0
movlw b'00000001' ; ndx 0 |B0
movwf mask ; |B0
btfsc work,0+4 ; bit 0 set? no, skip, else |B0
addwf mask,F ; ndx 3 or ndx 1 |B0
btfsc work,2+4 ; bit 2 set? no, skip, else |B0
swapf mask,F ; ndx 4..7 |B0
movf mask,W ; wreg = mask |B0
return ; |B0
;******************************************************************
; delay range: 11..327688 usecs in 5 usec steps (4 MHz clock)
;
delay
movlw high((250000-11)/5)+1
movwf delayhi
movlw low ((250000-11)/5)
dloop addlw -1 ; subtract 5 cycle loop time |B0
skpc ; borrow? no, skip, else |B0
decfsz delayhi,F ; done? yes, skip, else |B0
goto dloop ; do another 5 cycle loop |B0
return ; |B0
;******************************************************************
; outline table - 28 row/col dot positions in packed BCD format
;
boxtbl
retlw 0x77 ; row 7 col 7 (top left) |B0
retlw 0x76 ; row 7 col 6 |B0
retlw 0x75 ; row 7 col 5 |B0
retlw 0x74 ; row 7 col 4 |B0
retlw 0x73 ; row 7 col 3 |B0
retlw 0x72 ; row 7 col 2 |B0
retlw 0x71 ; row 7 col 1 |B0
retlw 0x70 ; row 7 col 0 (top right) |B0
retlw 0x60 ; row 6 col 0 |B0
retlw 0x50 ; row 5 col 0 |B0
retlw 0x40 ; row 4 col 0 |B0
retlw 0x30 ; row 3 col 0 |B0
retlw 0x20 ; row 2 col 0 |B0
retlw 0x10 ; row 1 col 0 |B0
retlw 0x00 ; row 0 col 0 (bottom right) |B0
retlw 0x01 ; row 0 col 1 |B0
retlw 0x02 ; row 0 col 2 |B0
retlw 0x03 ; row 0 col 3 |B0
retlw 0x04 ; row 0 col 4 |B0
retlw 0x05 ; row 0 col 5 |B0
retlw 0x06 ; row 0 col 6 |B0
retlw 0x07 ; row 0 col 7 (bottom left) |B0
retlw 0x17 ; row 1 col 7 |B0
retlw 0x27 ; row 2 col 7 |B0
retlw 0x37 ; row 3 col 7 |B0
retlw 0x47 ; row 4 col 7 |B0
retlw 0x57 ; row 5 col 7 |B0
retlw 0x67 ; row 6 col 7 |B0
tblprep
movlw boxtbl%256 ; boxtbl address lo |B0
movwf ptrl ; |B0
movlw boxtbl/256 ; boxtbl address hi |B0
movwf ptrh ; |B0
goto rdtable ; |B0
;******************************************************************
end