I was following this thread at electro-tech-online.com and decided to build a new, bigger LED cube. I'm controlling it with a PIC 12F509 and a Micrel MM5451YN. I'm using the bare-bones 12F509 only because that's what the original poster in the thread was using.
The MM5451YN is a 35-bit shift register with open drain drivers. I use the first 16 bits to control the cathodes of my common-anode cube, and the next 4 bits to control the anodes for each "level". I scraped through the bottom of my transistor bin and found four 2N4403 PNP's to use as high-side switches for multiplexing the levels. Here's a YouTube movie of the cube in action. Only one pattern for now: Here I'm testing out the MM5451YN (left). On the right is a pic of my 4x4 LED jig. The holes are drilled on 1" centers. I solder together one level at a time. 
A bit closer view of a level being assembled (left). A completed level pulled out of the jig and flipped over (right). 
Three completed levels, ready to be put together (left). Two levels soldered together (right). 
Completed cube (left). Control wiring soldered to cube (right). 
Another view of the control lines (left). The breadboard with anode driver transistors upper right (right). 
Completed hardware blinking LEDs (left). Closeup of the PIC and the two SPDT switches for isolation of the PGD/PGC lines for programming (right). 
This piece of code has a pattern that lights LEDs in a spiral animation, starting at the bottom and spiraling around the outside to the top. Other animations can be built in the "patt3" table, but you have to be careful not to make them too big or they push the code past the 12F509's "half-page limit" (256 bytes) for subroutine calls, and the program breaks. spiral.asm include "P12F509.INC" __config _IntRC_OSC & _WDT_OFF & _MCLRE_ON
D equ 0 CP equ 1
cblock 0x07 d1,d2,d3,count,count2,patlen,patrep,temp,anode,offset,fsr1,frames,cathptr plex,cath1a,cath1b,cath2a,cath2b,cath3a,cath3b,cath4a,cath4b endc
org 0x000 goto init patt3 addwf PCL,f retlw 0x10 ;pattern length - # of frames retlw 0x0a ;# of reps
retlw 0x88 retlw 0x88 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00
retlw 0x00 retlw 0x0f retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00
retlw 0x11 retlw 0x11 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00
retlw 0xf0 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00
retlw 0x00 retlw 0x00 retlw 0x88 retlw 0x88 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00
retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x0f retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00
retlw 0x00 retlw 0x00 retlw 0x11 retlw 0x11 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00
retlw 0x00 retlw 0x00 retlw 0xf0 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00
retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x88 retlw 0x88 retlw 0x00 retlw 0x00
retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x0f retlw 0x00 retlw 0x00
retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x11 retlw 0x11 retlw 0x00 retlw 0x00
retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0xf0 retlw 0x00 retlw 0x00 retlw 0x00
retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x88 retlw 0x88
retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x0f
retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x11 retlw 0x11
retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0xf0 retlw 0x00
init movlw b'11001000' ;clear T0CS for output on GPIO2 option movlw b'00001000' ;set pins to all outs tris GPIO clrf GPIO ;zero all pins movlw 0x08 ;set start level movwf anode movlw cathptr ;set cathode pointer movwf cathptr clrf plex bcf GPIO,D ;init MM5451 nop bsf GPIO,CP nop bcf GPIO,CP
spiral clrf offset ;point to start of table movf offset,w ;get pattern length call patt3 movwf patlen incf offset,f ;get # of reps movf offset,w call patt3 movwf patrep incf offset,f spir1 call isr ;multiplex 256 times decfsz plex,f goto spir1 anim movlw 0x08 ;set bytes per frame counter - 8 bytes movwf count movlw cath1a ;cathode pointer storage movwf FSR mloop movf offset,w ;get a byte of new pattern call patt3 movwf INDF incf offset,f ;increment pointers incf FSR,f decfsz count,f ;frame done? goto mloop decfsz patlen,f ;pattern done? goto spir1 reset movlw 0x02 ;point to start of frames in table movwf offset decfsz patrep,f ;# of reps complete? goto spir2 ;no, fix patlen and go again goto bail ;yes, done spir2 movlw 0 ;get patlen again call patt3 movwf patlen goto spir1 bail goto spiral
;*************************** ;"interrupt" service routine isr rlf anode,f ;change to next level movlw 2 ;increment cathode pointer addwf cathptr,f movlw 0x10 ;is anode > 0x08? subwf anode,w btfss STATUS,Z goto shift ;no, go ahead movlw 1 ;yes, reset to anode 1 movwf anode movlw cath1b ;and reset cathode pointer movwf cathptr shift movf cathptr,w ;load FSR movwf FSR bsf GPIO,D ;shift out start bit nop bsf GPIO,CP nop bcf GPIO,CP
movlw 0x02 ;set byte counter movwf count2 shift5 movlw 0x08 ;set loop counter movwf count movf INDF,w ;get a byte movwf temp shift1 rrf temp,f ;rotate ms-bit into carry btfsc STATUS,C ;is it 0? goto shift2 ;no, shift out a 1 goto shift3 ;yes, shift out a 0 shift2 bsf GPIO,D nop bsf GPIO,CP ;blip clock nop bcf GPIO,CP goto shift4 shift3 bcf GPIO,D nop bsf GPIO,CP ;blip clock nop bcf GPIO,CP shift4 decfsz count,f ;done 8-bits? goto shift1 ;no, go again decfsz count2,f goto shift6 goto shanode ;done cathodes - go do anode shift6 decf FSR,f goto shift5
shanode movlw 0x08 ;shift out anode byte movwf count movf anode,w movwf temp shan1 rrf temp,f btfsc STATUS,C goto shan2 goto shan3 shan2 bsf GPIO,D nop bsf GPIO,CP nop bcf GPIO,CP goto shan4 shan3 bcf GPIO,D nop bsf GPIO,CP nop bcf GPIO,CP shan4 decfsz count,f goto shan1
last3 movlw 0x0b ;shift out last 11 bits movwf count l3loop bcf GPIO,D nop bsf GPIO,CP nop bcf GPIO,CP decfsz count,f goto l3loop retlw 0
end |