 INCLUDE "p16f688.inc"
 __CONFIG    _CP_OFF & _CPD_OFF & _BOD_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _MCLRE_ON & _FCMEN_OFF & _IESO_OFF & _INTOSCIO
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Cory Helmuth Snowfall Tubes (With Tail)
; 8x7 Charlieplexed for 56 Falling LED's
; Original Design Concept Around Apr-14-2011
; Pinouts as Follows
;
;1 = RA4
;2 = RA0
;3 = RA1
;4 = RA2
;5 = RC0
;6 = RC1
;7 = RC2
;8 = RC3
;
;1-2 Done;1-3 Done;1-4 Done;1-5 Done;1-6 Done;1-7 Done;1-8 Done
;2-3 Done;2-4 Done;2-5 Done;2-6 Done;2-7 Done;2-8 Done
;3-4 Done;3-5 Done;3-6 Done;3-7 Done;3-8 Done
;4-5 Done;4-6 Done;4-7 Done;4-8 Done
;5-6 Done;5-7 Done;5-8 Done
;6-7 Done;6-8 Done
;7-8 Done
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Notes :
;  MUST LEAVE BANK BEFORE INCREMENTING NUMBER
;  SUBLW and SUBWF
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;  May-10-2011 : Updated / Redesigned / Overhauled Original Code
;                Added a PWM "Tail" 4 LED's Total
;                I know this Code is UGLY but it works and I don't think it's bad
;                for only using Assembly for about 4 weeks
;                No Warrantly Expressed of Implied You break it you buy it
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;  Sept-19-2011 : This is Diag software moves through one LED at a time slowely to
;                 help figure out ghosting issues and other problems.

 movlw b'00000000'               ;Turns off analog Outputs
 movwf ANSEL  
 movlw b'00000111'
 movwf CMCON0  

PC		equ 02                   ;Sets PC equal to the PC Counter
 cblock 0x020                    ;Start cblock at 0x20
 start_count, fall_count         ;start_count identifies which LED is brightest, fall_count tells reset.
 Dim100                          ;Dimmer variables used to set how often LED fires.
 Status1A                        ; Variables for status bits for port A's 4 LED's
 Status1C                        ; Variables for status bits for port C's 4 LED's
 Bit1A                           ; Variables for high/low bits for port A's 4 LED's
 Bit1C                           ; Variables for high/low bits for port C's 4 LED's
 d1, d2                          ; Variables for MoveLED Delay
 endc                            ;Ends the cblock

 goto VeryBeginning              ;I put this in so I could have my data tables at
                                 ;the beginning of program so I don't overrun the PC

TableSetA	addwf	PC, 1        ;Datatable for TrisA
 retlw     b'101110'
 retlw     b'101101'
 retlw     b'101011'
 retlw     b'101111'
 retlw     b'101111'
 retlw     b'101111'
 retlw     b'101111'
 retlw     b'111100'
 retlw     b'111010'
 retlw     b'111110'
 retlw     b'111110'
 retlw     b'111110'
 retlw     b'111110'
 retlw     b'101110'
 retlw     b'111001'
 retlw     b'111101'
 retlw     b'111101'
 retlw     b'111101'
 retlw     b'111101'
 retlw     b'101101'
 retlw     b'111100'
 retlw     b'111011'
 retlw     b'111011'
 retlw     b'111011'
 retlw     b'111011'
 retlw     b'101011'
 retlw     b'111010'
 retlw     b'111001'
 retlw     b'111111'
 retlw     b'111111'
 retlw     b'111111'
 retlw     b'101111'
 retlw     b'111110'
 retlw     b'111101'
 retlw     b'111011'
 retlw     b'111111'
 retlw     b'111111'
 retlw     b'101111'
 retlw     b'111110'
 retlw     b'111101'
 retlw     b'111011'
 retlw     b'111111'
 retlw     b'111111'
 retlw     b'101111'
 retlw     b'111110'
 retlw     b'111101'
 retlw     b'111011'
 retlw     b'111111'
 retlw     b'111111'
 retlw     b'101111'
 retlw     b'111110'
 retlw     b'111101'
 retlw     b'111011'
 retlw     b'111111'
 retlw     b'111111'
 retlw     b'111111'
 return

TableSetC	addwf	PC, 1        ;Datatable for TrisC
 retlw     b'111111'
 retlw     b'111111'
 retlw     b'111111'
 retlw     b'111110'
 retlw     b'111101'
 retlw     b'111011'
 retlw     b'110111'
 retlw     b'111111'
 retlw     b'111111'
 retlw     b'111110'
 retlw     b'111101'
 retlw     b'111011'
 retlw     b'110111'
 retlw     b'111111'
 retlw     b'111111'
 retlw     b'111110'
 retlw     b'111101'
 retlw     b'111011'
 retlw     b'110111'
 retlw     b'111111'
 retlw     b'111111'
 retlw     b'111110'
 retlw     b'111101'
 retlw     b'111011'
 retlw     b'110111'
 retlw     b'111111'
 retlw     b'111111'
 retlw     b'111111'
 retlw     b'111100'
 retlw     b'111010'
 retlw     b'110110'
 retlw     b'111110'
 retlw     b'111110'
 retlw     b'111110'
 retlw     b'111110'
 retlw     b'111001'
 retlw     b'110101'
 retlw     b'111101'
 retlw     b'111101'
 retlw     b'111101'
 retlw     b'111101'
 retlw     b'111100'
 retlw     b'110011'
 retlw     b'111011'
 retlw     b'111011'
 retlw     b'111011'
 retlw     b'111011'
 retlw     b'111010'
 retlw     b'111001'
 retlw     b'110111'
 retlw     b'110111'
 retlw     b'110111'
 retlw     b'110111'
 retlw     b'110110'
 retlw     b'110101'
 retlw     b'110011'
 return

TableBitA	addwf	PC, 1        ;Datatable for PortA
 retlw     b'010000'
 retlw     b'010000'
 retlw     b'010000'
 retlw     b'010000'
 retlw     b'010000'
 retlw     b'010000'
 retlw     b'010000'
 retlw     b'000001'
 retlw     b'000001'
 retlw     b'000001'
 retlw     b'000001'
 retlw     b'000001'
 retlw     b'000001'
 retlw     b'000001'
 retlw     b'000010'
 retlw     b'000010'
 retlw     b'000010'
 retlw     b'000010'
 retlw     b'000010'
 retlw     b'000010'
 retlw     b'000010'
 retlw     b'000100'
 retlw     b'000100'
 retlw     b'000100'
 retlw     b'000100'
 retlw     b'000100'
 retlw     b'000100'
 retlw     b'000100'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 return

TableBitC	addwf	PC, 1        ;Datatable for PortC
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000000'
 retlw     b'000001'
 retlw     b'000001'
 retlw     b'000001'
 retlw     b'000001'
 retlw     b'000001'
 retlw     b'000001'
 retlw     b'000001'
 retlw     b'000010'
 retlw     b'000010'
 retlw     b'000010'
 retlw     b'000010'
 retlw     b'000010'
 retlw     b'000010'
 retlw     b'000010'
 retlw     b'000100'
 retlw     b'000100'
 retlw     b'000100'
 retlw     b'000100'
 retlw     b'000100'
 retlw     b'000100'
 retlw     b'000100'
 retlw     b'001000'
 retlw     b'001000'
 retlw     b'001000'
 retlw     b'001000'
 retlw     b'001000'
 retlw     b'001000'
 retlw     b'001000'
 return

VeryBeginning
 movlw d'150'                      ;Sets Speed of Fall also set this in "WhichLED"
 movwf d2                        ;Move W Register to d2 (Speed of Fall)
 movlw d'1'                      ;Sets how many cycles before LED fires
 movwf Dim100                    ;Move W Register to Dim100 (Brightest LED)

StartOver
 movlw d'0'                      ;Resets Counter to PC jumps in Datatables
 movwf start_count               ;Move W Register to start_count
 movlw d'56'                     ;Sets number of LED's to "fall" before reset
 movwf fall_count                ;Move W Register to fall_count

WhichLED
 movlw d'150'                      ;Sets Speed of Fall also set this in "VeryBeginning"
 movwf d2                        ;Move W Register to d2 (Speed of Fall)
 movfw start_count               ;Move start_count Into W Register
 call StatusA                    ;call StatusA to get and Set Status4A
 movfw start_count               ;Move start_count Into W Register
 call StatusC                    ;call StatusC to get and Set Statuc4C
 movfw start_count               ;Move start_count Into W Register
 call BitA                       ;call TableBitA to get and set Bit4A
 movfw start_count               ;Move start_count Into W Register
 call BitC                       ;call TableBitC to get and set Bit4C
 incf  start_count,1             ;Increment start_count by 1

Start                            ;Start of PWM Loop
D100                             ;D100 Brightest LED
 decfsz        Dim100,1          ;Decrease Dim100 if 0 Fire LED4 else goto MLED
 goto MLED                       ;Dim100 Wasn't 0 goto MLED
 call LED4                       ;Dim100 Was 0 call to LED4 to fire Brightest LED
MLED                             ;MLED Counter to decide when to move the LEDs
 decfsz        d1,1              ;Decrease d1 if 0 decrease d2 else goto Start(PWM loop)
 goto Start                      ;d1 Wasn't 0 goto Start(PWM loop)
 decfsz        d2,1              ;d1 Was 0 decrease d2 if 0 call to MoveLED else goto Start
 goto Start                      ;d2 Wasn't 0 goto Start(PWM loop)
 goto MoveLED                    ;d2 Was 0 goto to MoveLED to move LEDs
 goto Start                      ;Goto Start (I don't actually think this is needed)

MoveLED                          ;MoveLED Routine Moves The LED's
 CLRF Status1A                   ;Clear Status1A
 CLRF Status1C                   ;Clear Status1C
 CLRF Bit1A                      ;Clear Bit1A
 CLRF Bit1C                      ;Clear Bit1C

 decfsz fall_count,1              ;Decrease fall_count if 0 Start over Else goto WhichLED
 Goto WhichLED                    ;Goto WhichLED to get new bits got "4" variables
 Goto StartOver                   ;Once Finished with LoopLED Start Over

 return
 
LED4
 movlw d'1'                ;Sets how often LED4 fires
 movwf Dim100              ;Move W Register to Dim100
 BSF	 STATUS,5          ;This little Section I'll call
 movlw   b'111111'         ;the Ghost Buster.  Thank you 
 movwf   TRISA             ;P.Short this idea worked great
 movwf   TRISC             ;Don't Call Ghost Busters call
 BCF     STATUS,5          ;Phil he is the all knowing PIC guru.
 movfw   Status1A          ;Move Status1A to W Register
 BSF     STATUS,5          ;Go to Bank 1
 movwf   TRISA             ;Move W to TrisA
 BCF     STATUS,5          ;Come back to Bank 0
 movfw   Status1C          ;Move Status1C to W Register
 BSF     STATUS,5          ;Go to Bank 1
 movwf   TRISC             ;Move W to TrisC
 BCF     STATUS,5          ;Come back to Bank 0
 movfw   Bit1A             ;Move Bit1A to W Register
 movwf   PORTA             ;Move W to PortA
 movfw   Bit1C             ;Move Bit1C to W Register
 movwf   PORTC             ;Move W to PortC
 CLRW                      ;Clear W Register
 movwf   PORTA             ;Turn Off PortA
 movwf   PORTC             ;Turn Off PortC
 return

StatusA                          ;StatusA SubRoutine For Setting Status4A Bits
 call TableSetA                  ;call TableSetA subroutine get bits for Status4A
 movwf Status1A                  ;Move W Register to Status4A
 return                          ;Return from SubRoutine

StatusC                          ;StatusC SubRoutine For Setting Status4C Bits 
 call TableSetC                  ;call TableSetC subroutine get bits for Status4C
 movwf Status1C                  ;Move W Register to Statuc4C 
 return                          ;Return from SubRoutine

BitA                             ;StatusA SubRoutine For Setting Status4A Bits
 call TableBitA                  ;call TableSetA subroutine get bits for Status4A
 movwf Bit1A                     ;Move W Register to Status4A
 return                          ;Return from SubRoutine

BitC                             ;StatusC SubRoutine For Setting Status4C Bits 
 call TableBitC                  ;call TableSetC subroutine get bits for Status4C
 movwf Bit1C                     ;Move W Register to Statuc4C 
 return                          ;Return from SubRoutine

 End
