;	PLANETARY CLOCK 
;
;	COPYRIGHT 2006  
;	THE PAK ENGINEERS
;	3985 TONAWANDA CREEK ROAD
;	EAST AMHERST, NY 14051
;
;	SIMPLE CLOCK DESIGN THAT USES RINGS OF LEDS INSTEAD OF NUMBERS. 
;	THE OUTER RING IS HOURS AND CONSISTS OF 12 LEDS PLACED APPROPRIATELY.
;	THE NEXT INNER RING IS 10'S OF MINUTES AND CONSISTS OF 6 LEDS.  
;	THE NEXT RING INWARD IS UNITS OF MINUTES AND HAS 10 LEDS.
;	IF SECONDS ARE IMPLEMENTED TWO ADDITIONAL RINGS ARE USED: 
;	A 10'S OF SECONDS RING AND A UNITS OF SECONDS RING WITH 
;	THE INITS OF SECONDS BEING THE INNERMOST RING.
;	A CENTER LED IS ALSO USED TO PROVIDE A VISUAL REFERENCE.
;
;	THE LEDS ARE WIRED AS A MATRIX WITH COMMON RING AND COMMON
;	VALUE (1,2,3..ETC).  TO LIGHT A SPECIFIC LED A SINGLE RING AND 
;	SINGLE VALUE WIRE ARE DRIVEN (ONE POSITIVE AND ONE GROUND). 
;	COMMON CATHODE AND COMMON ANODE CIRCUITS ARE BOTH POSSIBLE BY 
;	INVERTING THE DRIVER VALUES.  THIS PARTICULAR DESIGN USES 
;	RINGS AS COMMON CATHODES AND VALUES AS COMMON ANODES.
;
;	NOTE:  THERE CAN'T BE A "0" HOUR TIME VALUE, THAT'S 
;	ACTUALLY "12".  IT CAN BE CONFUSING.  IT'S THE ONLY RING
;	THAT'S A COMPLETE CIRCLE.
;
;	ONLY ONE LED (EXCEPT THE CENTER LED) IS ON AT A TIME.
;	THE CENTER LED IS WIRED SEPARATELY.
;
;	TIMER 0 IS USED AS MAIN TIMEKEEPER.  INTERRUPT FLAG
;	IS POLLED RATHER THAN ACTUALLY USING AN INTERRUPT
;
;
;_________________________________________________________________________
;
;	PROCESSOR PIC16C73
;
;    BROWN OUT RESET ON
;    CODE PROTECT OFF 
;    POWER UP TIMER ON
;    WATCH DOG TIMER OFF
;    LOW POWER OSCILLATOR
;
;
;__________________________________________________________
;
;	SYSTEM REGISTERS
;
TIMER0	EQU 01;  TIMER0 REGISTER;  
OPTN	EQU 01;  THIS IS ACTUALLY ON SECOND PAGE (LOCATION 81)
STATUS	EQU 03;  STATUS REGISTER FOR OPERATIONAL FLAGS
PORTA	EQU 05;  
;			BIT 0 PIN 2--- HOUR RING (12 POSITIONS)	(ANODE)
;			BIT 1 PIN 3--- 10'S OF MINUTES RING (ANODE)
;			BIT 2 PIN 4--- 1'S OF MINUTES RING 	(ANODE)
;			BIT 3 PIN 5--- 10'S OF SECONDS RING (ANODE)
;			BIT 4 PIN 6--- NOT USED  OPEN COLLECTOR OUTPUT!!
;			BIT 5 PIN 7--- 1'S OF SECONDS RING	(ANODE)
;
PORTB	EQU 06
;			BIT 0 PIN 21--- UNITS 0'S (CATHODE)	ALSO HOUR 12
;			BIT 1 PIN 22--- UNITS 1'S (CATHODE)
;			BIT 2 PIN 23--- UNITS 2'S (CATHODE)
;			BIT 3 PIN 24--- UNITS 3'S (CATHODE)
;			BIT 4 PIN 25--- UNITS 4'S (CATHODE)
;			BIT 5 PIN 26--- UNITS 5'S (CATHODE)
;			BIT 0 PIN 27--- UNITS 6'S (CATHODE)
;			BIT 1 PIN 28--- UNITS 7'S (CATHODE)
;
PORTC	EQU 07
;			BIT 0 PIN 11---	INCREMENT MIN SWITCH (NORMALLY PULLED HIGH)
;			BIT 1 PIN 12--- INCREMENT HOUR SWITCH (NORMALLY PULLED HIGH)
;			BIT 2 PIN 13--- CENTER BICOLOR LED (RED) ANODE
;			BIT 3 PIN 14--- CENTER BICOLOR LED (GREEN) ANODE
;			BIT 4 PIN 15--- UNITS 8'S (CATHODE)	
;			BIT 5 PIN 16--- UNITS 9'S (CATHODE)
;			BIT 6 PIN 17--- UNITS 10'S (CATHODE)
;			BIT 7 PIN 18--- UNITS 11'S (CATHODE) (NOTE HOUR 12 IS "0" UNIT)
;
;
PORTD	EQU 08;  NOT PHYSICALLY USED BUT SET UP
PORTE	EQU 09;	 NOT PHYSICALLY USED BUT SET UP
INTRP	EQU 0X0B; INTERRUPT CONTROL REGISTER, BIT 2 IS TIMER0 FLAG 
;					LOCATED ON BOTH FIRST AND SECOND PAGE
;
;	WORK REGISTERS
SECLSB	EQU 0X20;   THESE REGISTERS HAVE ONLY A SINGLE BIT ON AT A TIME 
SECMSB	EQU 0X21;   CORRESPONDING TO THE PROPER LED.  10 BITS ARE NEEDED 
SEC10S	EQU 0X22
MINLSB	EQU 0X23;   FOR LSB VALUES (0-9) AND 6 ARE NEEDED FOR THE 10'S
MINMSB	EQU 0X24;   OF HOURS AND MINUTES (0-5).  12 BITS ARE NEEDED FOR 
MIN10S	EQU 0X25
HRLSB	EQU 0X26;   HOURS.  BITS ARE SHIFTED TO MAINTAIN TIME AND THEN
HRMSB	EQU 0X27;   MASKED INTO OUTPUT REGISTERS AS REQUIRED.
;
DLY20	EQU 0X28;  	20 MS DELAY COUNTER
WRK1	EQU 0X29;	GP WORK REGISTER
SWTREG	EQU 0X2A;	USED FOR DEBOUNCE CONTROL
CENLED	EQU 0X2B;   COUNTER FOR CENTER LED CONTROL
;
;________________________________________________________________
START
	ORG 0000;   NOP TO SKIP AROUND INTERRUPT VECTOR (NOT USED) AT 0004
	NOP;			JUST TO BE SAFE
	NOP
	NOP
	NOP
	NOP
	NOP
;
	BSF STATUS, 5; GO TO SECOND PAGE TO SET PORT CONTROL REGISTERS
	CLRF PORTA;  SET PORTA CONTROL TO ALL '0' OR ALL OUTPUTS
	CLRF PORTB;  SET PORTB TO ALL OUTOUTS
	MOVLW 0X03; (0000 0011) BITS 0&1 ARE SWITCH INPUTS
	MOVWF PORTC; ALL OTHERS ARE LED OUTPUTS
	CLRF PORTD;  NOT USED, SET TO OUTPUTS 
	CLRF PORTE;  NOT USED, SET TO OUTPUT 
;
;		SET UP TIMER0 CONTROL BITS (SECOND PAGE AS WELL)
	CLRF INTRP;  TURN OFF ALL INTERRUPTS;  FLAGS WILL STILL BE SET
				; AND WILL BE POLLED.  INTERRUPTS NOT USED.
;
	MOVLW 0X04  ; (0000 0100),  PRESCALE TO 1/32 AND ASSIGN TO TIMER0 
	MOVWF OPTN;	32768 CLOCK=8192 INTERNAL CLOCK, PRESCALE DIVIDE BY 32
;				 AND THEN BY 256 (TIMER0 OVERFLOW) GIVES ONE SECOND
;
	BCF STATUS, 5;  GO BACK TO FIRST PAGE
;
	MOVLW 01; 
	MOVWF	SECLSB; SETS ALL DISPLAY REGISTERS TO 0000 0001 
	MOVWF	MINLSB;	WHICH TURNS ON THE LSB OF EACH RING
	MOVWF	HRLSB;	THIS DISPLAYS 00:00:00
	MOVWF   SEC10S;
	MOVWF   MIN10S;
	MOVWF 	CENLED; START LOOP COUNTER AT 1 FOR CENTER LED CONTROL
;
	CLRF	MINMSB;	HIGH ORDER BITS SET TO 00
	CLRF	HRMSB;	
	CLRF	SECMSB;	
	CLRF 	SWTREG
	CLRF 	PORTC
;
;
MAINLOOP;
  	BTFSC INTRP, 2;  CHECK TO SEE IF TIMER0 OVERFLOW FLAG IS SET (NORMALLY 0)  
	CALL GOTSEC;     IF SO THEN A SECOND HAS ELAPSED  (FLOW-TESTED WORKS)
	CALL CHKMIN;	CHECK TO SEE IF SET-MINUTE BUTTON IS PRESSED
	CALL CHKHR;		CHECK TO SEE IF SET-HOUR BUTTON IS PRESSED
	CALL DRVLED;  	 DRIVE LEDS FOR 100 MS TOTAL (20 MS/RING)
	CALL DRVCNTR;	 DRIVE CENTER LED AT DIFFEERNT RATE
	GOTO MAINLOOP;
;
;	_______________________SUBROUTINES NEXT_____________________
;
DRVCNTR;   TOGGLE THE CENTER BI-COLOR LED  PORTC 6 AND 7
	DECFSZ CENLED, 1;  SETS ZERO FLAG TOO
	RETURN;    
	MOVLW 0X05; 5 TIMES MAIN LOOP=500 MS OR 1/2 SEC
	MOVWF CENLED; RELOAD COUNTER
TOGL;
	BTFSC PORTC, 2;  CHECK FOR PRESENT STATE
	GOTO PRT6ON
PRT6OFF;       PORTA6 IS OFF SO TURN IT ON ABD TURN PORTC7 OFF
	BSF PORTC, 2;  TURN IT ON
	BCF PORTC, 3;  TURN IT OFF
	CALL DELAY20MS
	RETURN
PRT6ON;  	NOW ON SO TURN IT OFF AND TURN ON PORTC7
	BCF PORTC, 2
	BSF PORTC, 3;
	CALL DELAY20MS
	RETURN
;________________________________________________________________
;
GOTSEC;	 TIMERO OVERFLOW SO A FULL SECOND HAS ELAPSED (FLOW-TESTED AND WORKS)
	BCF INTRP, 2;  RESET INTERRUPT FLAG
;
;	FIVE SHIFT-REGISTERS REPRESENT THE 5 RINGS IN THE DISPLAY. 
;	UNITS OF SECONDS AND UNITS OF MINUTES RINGS NEED 10 BITS OR
;	TWO 8-BIT REGISTERS (xxxLSB AND xxxMSB).  
;	10'S OF MINUTES AND 10'S OF SECONDS RINGS USE ONLY 6 BITS AND REQUIRE
;	ONLY A SINGLE REGISTER (xxx10S).
;	THE HOURS RING USES 12 BITS AND NEEDS TWO REGISTERS (HRLSB AND HRMSB)
;
;	SINCE THESE REGISTER BITS REPRESENT A SINGLE LED AN INCREMENT IS  
;	REALLY A LEFT SHIFT.  LIGHT THE NEXT LED IN ORDER (NOT COUNT)
;	NOTE THAT ALL ROTATES ARE THROUGH THE CARRY BIT
;
;		SECONDS IS 10 BITS USING TWO REGISTERS
	BCF STATUS, 0; CLEAR CARRY BIT
	RLF SECLSB, 1;  FIRST 8 BITS (OUT OF 10) FOR SECONDS  
	RLF SECMSB, 1;  LAST 2 BITS
	BTFSS SECMSB, 2;  IF 0000 0100 THEN 10 SECONDS
	RETURN;  NO CARRY SO DO NOTHING MORE
;
GOT10SEC;     ONLY 6 BITS
	CLRF SECLSB; RESET UNITS OF SECONDS REGISTERS
	CLRF SECMSB;
	INCF SECLSB,1;  TURN ON "0" VALUE IN UNITS OF SECONDS
	BCF STATUS, 0; CLEAR CARRY BIT
	RLF SEC10S, 1;  GOT TEN SECONDS SO INCREMENT REGISTER
	BTFSS SEC10S, 6;  IF 0100 0000 THEN 60 SECONDS HAS ELAPSED
	RETURN;  
;
GOTMIN;  INCREMENT MINUTES (10 BITS) BUT FIRST RESET 10'S OF SEC
	CLRF SEC10S
	INCF SEC10S, 1;  TURN ON ONLY LSB ("0") OF 10'S OF SECONDS REGISTER
	BCF STATUS, 0; CLEAR CARRY
	RLF MINLSB, 1
	RLF MINMSB, 1;  INC MINUTE REGISTERS
	BTFSS MINMSB, 2;  IF 0000 0100 THEN GOT 10 MINUTES
	RETURN;  IF NOT GO BACK
;
GOT10MIN;		10'S OF MINUTES IS 6 BITS
	CLRF MINLSB;  FIRST RESET UNITS OF MINUTES REGISTERS
	CLRF MINMSB
	INCF MINLSB, 1;  TURN ON "0" IN UNITS OF MINUTES
	BCF STATUS, 0;  RESET CARRY FLAG
	RLF MIN10S, 1;  INCREMENT 10'S OF MINUTES 
	BTFSS MIN10S, 6;  IF 0100 0000 THEN GOT A FULL HOUR
	RETURN;  IF NOT THEN GO BACK
;
GOTHR;		HOURS IS 12 BITS
	CLRF MIN10S;
	INCF MIN10S, 1;  TURN ON "0" IN 10'S OF MINUTES RING
	BCF STATUS, 0; CLEAR CARRY
	RLF HRLSB, 1
	RLF HRMSB, 1;  INCREMENET REGISTERS
	BTFSS HRMSB, 4; IF 0001 0000 THEN ITS 12:00:00 AND HAVE TO RESET
					;NOTE THAT "0" O'CLOCK IS REALLY 12
	RETURN;  NOT 12 SO GO BACK
	CLRF HRMSB;  RESET HOURS RING
	CLRF HRLSB
	INCF HRLSB, 1;  TURN ON "12" HOUR LED
	RETURN

;
;________________________________________________________________
;
CHKMIN;		SEE IF SET-MINUTE SWITCH IS PRESSED (=0)
	BTFSC SWTREG, 0;  NOTE THAT REG IS POS-TRUE AND ACTUAL SWITCH IS NEG=TRUE
	GOTO MINWASON;  CHK FOR CONTINUATION OF SWT PRESS
;
MINWASOFF;    CHECK FOR NEWLY-PRESSED SWT
	BTFSC PORTC, 0;  IF 0 THEN NEWLY PRESSED
	RETURN;  WAS OFF AND IS STILL OFF SO GO BACK
NEWMINPRESS;
	CALL DELAY20MS;  DEBOUNCE
	BSF SWTREG, 0;  SET REGISTER TO SHOW SWITCH IS PRESSED
INCMIN;  INCREMENT MINUTES (10 BITS) BUT FIRST RESET 10'S OF SEC
	BCF STATUS, 0; CLEAR CARRY
	RLF MINLSB, 1
	RLF MINMSB, 1;  INC MINUTE REGISTERS
	BTFSS MINMSB, 2;  IF 0000 0100 THEN GOT 10 MINUTES
	RETURN;  IF NOT GO BACK
INC10MIN;		10'S OF MINUTES IS 6 BITS
	CLRF MINLSB;  FIRST RESET UNITS OF MINUTES REGISTERS
	CLRF MINMSB
	INCF MINLSB, 1;  TURN ON "0" IN UNITS OF MINUTES
	BCF STATUS, 0;  RESET CARRY FLAG
	RLF MIN10S, 1;  INCREMENT 10'S OF MINUTES 
	BTFSS MIN10S, 6;  IF 0100 0000 THEN GOT A FULL HOUR
	RETURN;  IF NOT THEN GO BACK
	CLRF MIN10S;   RESET 
	INCF MIN10S, 1;  
;
MINWASON;
	BTFSS PORTC, 0;  IF 0 THEN STILL PRESSED FROM LAST TIME
	RETURN;     GO BACK, NOTHING TO DO
;
NEWMINOFF;		SWT RELEASED AFTER BEING PRESSED		
	CALL DELAY20MS;  DEBOUNCE
	BCF SWTREG, 0;	CLEAR PRESS INDICATION AND GO BACK
	RETURN
;
;______________________________________________
;
CHKHR;		SEE IF SET-HOUR SWITCH IS PRESSED (=0)
	BTFSC SWTREG, 1;  NOTE THAT REG IS POS-TRUE AND ACTUAL SWITCH IS NEG=TRUE
	GOTO HRWASON;  CHK FOR CONTINUATION OF SWT PRESS
;
HRWASOFF;    CHECK FOR NEWLY-PRESSED SWT
	BTFSC PORTC, 1;  IF 0 THEN NEWLY PRESSED
	RETURN;  WAS OFF AND IS STILL OFF SO GO BACK
NEWHRPRESS;
	CALL DELAY20MS;  DEBOUNCE
	BSF SWTREG, 1;  SET REGISTER TO SHOW SWITCH IS PRESSED
INCHR;			INCREMENT THE HOUR REGISTERS
	BCF STATUS, 0; CLEAR CARRY
	RLF HRLSB, 1
	RLF HRMSB, 1;  INCREMENET REGISTERS
	BTFSS HRMSB, 4; IF 0001 0000 THEN ITS 12:00:00 AND HAVE TO RESET
					;NOTE THAT "0" O'CLOCK IS REALLY 12
	RETURN;  NOT 12 SO GO BACK
	CLRF HRMSB;  RESET HOURS RING
	CLRF HRLSB
	INCF HRLSB, 1;  TURN ON "12" HOUR LED
	RETURN

HRWASON;
	BTFSS PORTC, 1;  IF 0 THEN STILL PRESSED FROM LAST TIME
	RETURN;     GO BACK, NOTHING TO DO
;
NEWHROFF;		SWT RELEASED AFTER BEING PRESSED		
	CALL DELAY20MS;  DEBOUNCE
	BCF SWTREG, 1;	CLEAR PRESS INDICATION AND GO BACK
	RETURN
;
;___________________________________________________
;
DRVLED;  TURN ON A CYCLE OF LEDS WITH A DELAY
;		RING MUST BE POSITIVE AND UNITS MUST BE NEGATIVE FOR
;		LED TO LIGHT UP
	CLRF PORTA; TURN OFF DRIVES TO RINGS TO BE SURE DISPLAY IS OFF
;
SECDRV;  
	MOVF SECLSB, 0;  LOAD W
	MOVWF PORTB; LOAD LOW ORDER 8 BITS
	COMF PORTB, 1;  OUTPUT MUST BE LOW TO LIGHT LED
	MOVLW 0XF0;  RESET MASK FOR HIGH NIBBLE OF PORT
	IORWF PORTC, 1;  SET HIGH ORDER BITS TO 1 (OFF)
	BTFSC SECMSB, 0;  NOW TEST AND TURN ON MSB BITS AS REQUIRED
	BCF PORTC, 4; CLEAR TURNS IT ON
 	BTFSC SECMSB, 1;  NOW TEST AND TURN ON MSB BITS AS REQUIRED
	BCF PORTC, 5; CLEAR TURNS IT ON
;	BTFSC SECLSB, 2;  NOW TEST AND TURN ON MSB BITS AS REQUIRED
;	BCF PORTC, 6; CLEAR TURNS IT ON	
;	BTFSC SECLSB, 3;  NOW TEST AND TURN ON MSB BITS AS REQUIRED
;	BCF PORTC, 7; CLEAR TURNS IT ON
	BSF PORTA, 5; TURN ON SECONDS RING
	CALL DELAY20MS; WAIT
	BCF PORTA, 5;  TURN IT OFF
;
SEC10DRV	
	MOVF SEC10S, 0;  LOAD W
	MOVWF PORTB; LOAD LOW ORDER 8 BITS
	COMF PORTB, 1;  OUTPUT MUST BE LOW TO LIGHT LED
	MOVLW 0XF0;  RESET MASK FOR HIGH NIBBLE OF PORT
	IORWF PORTC, 1;  SET HIGH ORDER BITS TO 1 (OFF)
	BSF PORTA, 3; TURN ON SECONDS RING
	CALL DELAY20MS; WAIT
	BCF PORTA, 3;  TURN IT OFF

MINDRV;
	MOVF MINLSB, 0;  LOAD W
	MOVWF PORTB; LOAD LOW ORDER 8 BITS
	COMF PORTB, 1;  OUTPUT MUST BE LOW TO LIGHT LED
	MOVLW 0XF0;  RESET MASK FOR HIGH NIBBLE OF PORT
	IORWF PORTC, 1;  SET HIGH ORDER BITS TO 1 (OFF)
	BTFSC MINMSB, 0;  NOW TEST AND TURN ON MSB BITS AS REQUIRED
	BCF PORTC, 4; CLEAR TURNS IT ON
 	BTFSC MINMSB, 1;  NOW TEST AND TURN ON MSB BITS AS REQUIRED
	BCF PORTC, 5; CLEAR TURNS IT ON
;	BTFSC MINLSB, 2;  NOW TEST AND TURN ON MSB BITS AS REQUIRED
;	BCF PORTC, 6; CLEAR TURNS IT ON	
;	BTFSC MINLSB, 3;  NOW TEST AND TURN ON MSB BITS AS REQUIRED
;	BCF PORTC, 7; CLEAR TURNS IT ON
	BSF PORTA, 2; TURN ON SECONDS RING
	CALL DELAY20MS; WAIT
	BCF PORTA, 2;  TURN IT OFF
;
MIN10DRV	
	MOVF MIN10S, 0;  LOAD W
	MOVWF PORTB; LOAD LOW ORDER 8 BITS
	COMF PORTB, 1;  OUTPUT MUST BE LOW TO LIGHT LED
	MOVLW 0XF0;  RESET MASK FOR HIGH NIBBLE OF PORT
	IORWF PORTC, 1;  SET HIGH ORDER BITS TO 1 (OFF)
	BSF PORTA, 1; TURN ON SECONDS RING
	CALL DELAY20MS; WAIT
	BCF PORTA, 1;  TURN IT OFF

HRDRV;
	MOVF HRLSB, 0;  LOAD W
	MOVWF PORTB; LOAD LOW ORDER 8 BITS
	COMF PORTB, 1;  OUTPUT MUST BE LOW TO LIGHT LED
	MOVLW 0XF0;  RESET MASK FOR HIGH NIBBLE OF PORT
	IORWF PORTC, 1;  SET HIGH ORDER BITS TO 1 (OFF)
	BTFSC HRMSB, 0;  NOW TEST AND TURN ON MSB BITS AS REQUIRED
	BCF PORTC, 4; CLEAR TURNS IT ON
 	BTFSC HRMSB, 1;  NOW TEST AND TURN ON MSB BITS AS REQUIRED
	BCF PORTC, 5; CLEAR TURNS IT ON
	BTFSC HRMSB, 2;  NOW TEST AND TURN ON MSB BITS AS REQUIRED
	BCF PORTC, 6; CLEAR TURNS IT ON	
	BTFSC HRMSB, 3;  NOW TEST AND TURN ON MSB BITS AS REQUIRED
	BCF PORTC, 7; CLEAR TURNS IT ON
	BSF PORTA, 0; TURN ON SECONDS RING
	CALL DELAY20MS; WAIT
	BCF PORTA, 0;  TURN IT OFF
;
	RETURN
;___________________________________________________
DELAY20MS;		DELAY 20 MS USED FOR DEBOUNCING AND LED LIGHTING
;				INSTRUCTIONS ARE 0.12207 SECONDS EACH
;				SO 164 INSTRUCTIONS ARE VERY CLOSE TO 20 MS
;				ACCURACY ISN'T IMPORTANT HERE
;				ACTUAL CYCLE COUNT IS 165 IN THIS ROUTINE
;;;;;;;;;;;;;;;;;;;	RETURN;   TEST ONLY  ****************************************

	MOVLW 0X10;  SET UP 16 LOOPS OF 10 INSTRUCTIONS
	MOVWF DLY20;  LOAD LOOP COUNTER
DLY20LP;
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	DECFSZ DLY20, 1; ONE CYCLE DURING LOOP
	RETURN; 2 CYCLES
	GOTO DLY20LP; 2 CYCLES,  10 TOTAL CYCLES INSIDE LOOP
;_______________________________________________________
;
	END  
	
