;// =================================================================
;//
;//  32x16 DOT MATRIX CLOCK FIRMWARE
;//
;//    (c)masa-u 2005.04.10
;//    http://www.mbin.jp/~masa-u/
;//
;//    Device: PIC16F876
;//    OSC:    12.800000 MHz
;//    Asm:    MPASM
;//
;// =================================================================

			include		p16f876.inc
			
			LIST		P=pic16f876
			
;//**** device configuration

			__config	_HS_OSC & _WDT_OFF & _PWRTE_OFF & _LVP_OFF
			
;//**** pin assignments

;			RA0 -> NC
;			RA1 -> NC
;			RA2 -> NC
;			RA3 -> NC
;			RA4 -> NC
;			RA5 -> NC

A_TRIS		equ			0x00

;			RB0-3 -> NC
;			RB4 -> LED CLK
;			RB5 -> LED LATCH
;			RB6 -> LED DATA H
;			RB7 -> LED DATA V

B_LEDCLK	equ			4		;// LED DATA CLOCK
B_LEDLAT	equ			5		;// LED LATCH
B_LEDDH		equ			6		;// LED HORIZONTAL DATA (32 bits)
B_LEDDV		equ			7		;// LED VERTICAL DATA (16 bits)
B_TRIS		equ			0x00

;			RC0 -> NC
;			RC1 -> NC
;			RC2 -> NC
;			RC3 -> NC
;			RC4 -> NC
;			RC5 <- BTN 5
;			RC6 <- BTN 6
;			RC7 <- BTN 7

C_BTN5		equ			5		;// BUTTON 5
C_BTN6		equ			6		;// BUTTON 6
C_BTN7		equ			7		;// BUTTON 7
C_TRIS		equ			0xE0


;//---- reserve F's (for direct access)

clk_hh		equ			0x20
clk_hl		equ			0x21
clk_mh		equ			0x22
clk_ml		equ			0x23
clk_sh		equ			0x24
clk_sl		equ			0x25
clk_tik0	equ			0x26
clk_tik1	equ			0x27

scany		equ			0x30
scanx		equ			0x31

hdata		equ			0x32
dmask		equ			0x33		;// data mask for interlaced display

btn6to		equ			0x34
btn7to		equ			0x35

arg0		equ			0x40
arg1		equ			0x41
savedW		equ			0x42
savedStat	equ			0x43

;//---- vector initialize

			org			0
_RESET_		goto		_Main
			org			4
			goto		_Intr
		

;//==========================================================================
;//==========================================================================
;//			MAIN PROGRAM
;//==========================================================================

;//==== main program

			org			8
_Main		call		_Init		;// initialize

			movlw		0x01
			movwf		clk_tik1
			clrf		clk_tik0
			clrf		clk_sl
			clrf		clk_sh
			clrf		clk_ml
			clrf		clk_mh
			clrf		clk_hl
			clrf		clk_hh
			clrf		dmask
			
			clrf		scanx
			clrf		scany
			clrf		PORTB
			
MAINLP		bsf			PORTB, B_LEDLAT
			clrf		scanx

			btfsc		PORTC, C_BTN5
			goto		I_DISP_NORM
					
I_DISP_SEC	movf		clk_sl, W
			call		_FONT_DIGIT
			xorlw		0xFF
			andwf		dmask, W
			movwf		arg0
			call		_Write8
			
			movf		clk_sh, W
			call		_FONT_DIGIT
			xorlw		0xFF
			andwf		dmask, W
			movwf		arg0
			call		_Write8

			movf		clk_ml, W
			call		_FONT_DIGIT
			andwf		dmask, W
			movwf		arg0
			call		_Write8

			movf		clk_mh, W
			call		_FONT_DIGIT
			andwf		dmask, W
			movwf		arg0
			call		_Write8
			goto		E_DISP
			
I_DISP_NORM	movf		clk_ml, W
			call		_FONT_DIGIT
			andwf		dmask, W
			movwf		arg0
			call		_Write8
			
			movf		clk_mh, W
			call		_FONT_DIGIT
			andwf		dmask, W
			movwf		arg0
			call		_Write8

			movf		clk_hl, W
			call		_FONT_DIGIT
			andwf		dmask, W
			movwf		arg0
			call		_Write8

			movf		clk_hh, W
			btfsc		STATUS, Z
			movlw		0x0A
			call		_FONT_DIGIT
			andwf		dmask, W
			movwf		arg0
			call		_Write8
			
E_DISP

			bcf			PORTB, B_LEDLAT
			nop
			bsf			PORTB, B_LEDLAT
			
			incf		scany, f
			movlw		0x0F
			andwf		scany, f
			btfss		STATUS, Z
			comf		dmask, f
			
			;// process buttons
I_BTN7		btfsc		PORTC, C_BTN7
			clrf		btn7to
			incf		btn7to, f
			btfss		STATUS, Z
			goto		E_BTN7
			btfsc		PORTC, C_BTN5
			call		_Inc_Hour
			call		_Zero_Sec
E_BTN7

I_BTN6		btfsc		PORTC, C_BTN6
			clrf		btn6to
			incf		btn6to, f
			btfss		STATUS, Z
			goto		E_BTN6
			btfsc		PORTC, C_BTN5
			call		_Inc_Min
			call		_Zero_Sec
E_BTN6

			goto		MAINLP
			

			
;//----	initializer
_Init		clrf		PORTA
			clrf		PORTB
			clrf		PORTC
					
			;// --- go to bank 1
			bsf			STATUS, RP0
			
			;// set input-output flag
			movlw		A_TRIS
			movwf		TRISA
			movlw		B_TRIS
			movwf		TRISB
			movlw		C_TRIS
			movwf		TRISC
			
			;// --- back to bank 0
			bcf			STATUS, RP0
			
			;// ==================================
			;// --- go to bank 1
			bsf			STATUS, RP0
			
			bcf			OPTION_REG, T0CS	;// fOSC/4 clock
			bcf			OPTION_REG, PSA		;// TMR0 prescaler
			bcf			OPTION_REG, PS2
			bcf			OPTION_REG, PS1
			bsf			OPTION_REG, PS0		;// 1:4 prescaler
			
			;// --- back to bank 0
			bcf			STATUS, RP0
			
			bcf			INTCON, T0IF
			bsf			INTCON, T0IE
			bsf			INTCON, GIE
			
			return


;//==========================================================================
;//			INTERRUPTS
;//==========================================================================

_Intr		;// save registers
			movwf		savedW
			swapf		STATUS, W
			movwf		savedStat

			bcf			INTCON, T0IF
						
			;// decrement tick low-order
			decf		clk_tik0, f
			btfss		STATUS, Z
			goto		E_INTR
			
			;// decrement tick high-order
			decf		clk_tik1, f
			btfss		STATUS, Z
			goto		E_INTR
			
			;// 1 second elapsed, restore tick (0x0C35)
			call		_Rst_Tick
			
			;// increment second
			call		_Inc_Sec

			;// restore registers
E_INTR		swapf		savedStat, W
			movwf		STATUS
			swapf		savedW, f
			swapf		savedW, W
						
			retfie
			
			
;//==========================================================================
;//			OTHER FUNCTIONS
;//==========================================================================


_Rst_Tick	;// restore tick (0x0C35 -> 0x0D 0x35)
			movlw		0x0D
			movwf		clk_tik1
			movlw		0x35
			movwf		clk_tik0
			return

_Zero_Sec	;// reset second counter
			call		_Rst_Tick
			clrf		clk_sl
			clrf		clk_sh
			return
			
_Inc_Sec	;// increment second 1's
			incf		clk_sl, f
			movlw		0x0A
			xorwf		clk_sl, W
			btfss		STATUS, Z
			return
			
			clrf		clk_sl
			
			;// increment second 10's
			incf		clk_sh, f
			movlw		0x06
			xorwf		clk_sh, W
			btfss		STATUS, Z
			return
			
			clrf		clk_sh
			goto		_Inc_Min
			
_Inc_Min	;// increment minute 1's
			incf		clk_ml, f
			movlw		0x0A
			xorwf		clk_ml, W
			btfss		STATUS, Z
			return
			
			clrf		clk_ml
			
			;// increment second 10's
			incf		clk_mh, f
			movlw		0x06
			xorwf		clk_mh, W
			btfss		STATUS, Z
			return
			
			clrf		clk_mh
			goto		_Inc_Hour
			
_Inc_Hour	;// increment hour
			incf		clk_hl, f
			movlw		0x0A
			xorwf		clk_hl, W
			btfss		STATUS, Z
			goto		I_CLK_HL_CHK24
			
			clrf		clk_hl
			incf		clk_hh
			return
			
I_CLK_HL_CHK24
			movlw		0x04
			xorwf		clk_hl, W
			btfss		STATUS, Z
			return
			movlw		0x02
			xorwf		clk_hh, W
			btfss		STATUS, Z
			return
			
			clrf		clk_hh
			clrf		clk_hl
			return
			

_Write8		;// write 8 dots to led
			;// arg0 -> data
			
			call		_Write1
			call		_Write1
			call		_Write1
			call		_Write1

			call		_Write1
			call		_Write1
			call		_Write1
			call		_Write1

			return
			
						
_Write1		;// write 1 dot to led
			;// arg0 <-> data
			bcf			PORTB, B_LEDDH
			btfsc		arg0, 0
			bsf			PORTB, B_LEDDH
			
			bcf			PORTB, B_LEDDV
			movlw		0x0F
			andwf		scanx, W
			xorwf		scany, W
			btfsc		STATUS, Z
			bsf			PORTB, B_LEDDV
			
			rrf			arg0, f
			incf		scanx, f
			
			bsf			PORTB, B_LEDCLK
			nop
			bcf			PORTB, B_LEDCLK
			return
			
			
;//==========================================================================
;//			FONT DATA FUNCTION
;//==========================================================================

			org			0x100
kFntFn_PCLATH	equ			1

_FONT_DIGIT	;// return font of a digit (W)
			;// W -> digit to return
			movwf		arg0
			movlw		kFntFn_PCLATH
			movwf		PCLATH
			
			movlw		0x0F
			andwf		arg0, W
			addwf		PCL, f
			goto		_FONT_0
			goto		_FONT_1
			goto		_FONT_2
			goto		_FONT_3
			goto		_FONT_4
			goto		_FONT_5
			goto		_FONT_6
			goto		_FONT_7
			goto		_FONT_8
			goto		_FONT_9
			goto		_FONT__
			goto		_FONT__
			goto		_FONT__
			goto		_FONT__
			goto		_FONT__
			goto		_FONT__
			
			
_FONT_0		;// return font of 0
			movlw		kFntFn_PCLATH
			movwf		PCLATH
			
			movlw		0x0F
			andwf		scany, W
			addwf		PCL, f
			retlw		b'00000000'
			retlw		b'01111100'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'01111100'
			retlw		b'00000000'

_FONT_1		;// return font of 1
			movlw		kFntFn_PCLATH
			movwf		PCLATH
			
			movlw		0x0F
			andwf		scany, W
			addwf		PCL, f
			retlw		b'00000000'
			retlw		b'00011000'
			retlw		b'00111000'
			retlw		b'01011000'
			retlw		b'00011000'
			retlw		b'00011000'
			retlw		b'00011000'
			retlw		b'00011000'
			retlw		b'00011000'
			retlw		b'00011000'
			retlw		b'00011000'
			retlw		b'00011000'
			retlw		b'00011000'
			retlw		b'00011000'
			retlw		b'01111110'
			retlw		b'00000000'

_FONT_2		;// return font of 2
			movlw		kFntFn_PCLATH
			movwf		PCLATH
			
			movlw		0x0F
			andwf		scany, W
			addwf		PCL, f
			retlw		b'00000000'
			retlw		b'01111100'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'00000110'
			retlw		b'00000110'
			retlw		b'00000110'
			retlw		b'00000110'
			retlw		b'00001100'
			retlw		b'00011000'
			retlw		b'00110000'
			retlw		b'01100000'
			retlw		b'11000000'
			retlw		b'11000000'
			retlw		b'11111110'
			retlw		b'00000000'

_FONT_3		;// return font of 3
			movlw		kFntFn_PCLATH
			movwf		PCLATH
			
			movlw		0x0F
			andwf		scany, W
			addwf		PCL, f
			retlw		b'00000000'
			retlw		b'01111100'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'00000110'
			retlw		b'00000110'
			retlw		b'00000110'
			retlw		b'00111100'
			retlw		b'00000110'
			retlw		b'00000110'
			retlw		b'00000110'
			retlw		b'00000110'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'01111100'
			retlw		b'00000000'

_FONT_4		;// return font of 4
			movlw		kFntFn_PCLATH
			movwf		PCLATH
			
			movlw		0x0F
			andwf		scany, W
			addwf		PCL, f
			retlw		b'00000000'
			retlw		b'00001100'
			retlw		b'00011100'
			retlw		b'00101100'
			retlw		b'01001100'
			retlw		b'01001100'
			retlw		b'01001100'
			retlw		b'10001100'
			retlw		b'10001100'
			retlw		b'10001100'
			retlw		b'11111110'
			retlw		b'00001100'
			retlw		b'00001100'
			retlw		b'00001100'
			retlw		b'00001100'
			retlw		b'00000000'

_FONT_5		;// return font of 5
			movlw		kFntFn_PCLATH
			movwf		PCLATH
			
			movlw		0x0F
			andwf		scany, W
			addwf		PCL, f
			retlw		b'00000000'
			retlw		b'11111110'
			retlw		b'10000000'
			retlw		b'10000000'
			retlw		b'10000000'
			retlw		b'10000000'
			retlw		b'10000000'
			retlw		b'11111100'
			retlw		b'00000110'
			retlw		b'00000110'
			retlw		b'00000110'
			retlw		b'00000110'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'01111100'
			retlw		b'00000000'

_FONT_6		;// return font of 6
			movlw		kFntFn_PCLATH
			movwf		PCLATH
			
			movlw		0x0F
			andwf		scany, W
			addwf		PCL, f
			retlw		b'00000000'
			retlw		b'00111100'
			retlw		b'01100000'
			retlw		b'11000000'
			retlw		b'11000000'
			retlw		b'11000000'
			retlw		b'11111100'
			retlw		b'11000010'
			retlw		b'11000010'
			retlw		b'11000010'
			retlw		b'11000010'
			retlw		b'11000010'
			retlw		b'11000010'
			retlw		b'11000010'
			retlw		b'01111100'
			retlw		b'00000000'

_FONT_7		;// return font of 7
			movlw		kFntFn_PCLATH
			movwf		PCLATH
			
			movlw		0x0F
			andwf		scany, W
			addwf		PCL, f
			retlw		b'00000000'
			retlw		b'11111110'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'00000110'
			retlw		b'00000110'
			retlw		b'00001100'
			retlw		b'00001100'
			retlw		b'00001100'
			retlw		b'00011000'
			retlw		b'00011000'
			retlw		b'00011000'
			retlw		b'00110000'
			retlw		b'00110000'
			retlw		b'00110000'
			retlw		b'00000000'

_FONT_8		;// return font of 8
			movlw		kFntFn_PCLATH
			movwf		PCLATH
			
			movlw		0x0F
			andwf		scany, W
			addwf		PCL, f
			retlw		b'00000000'
			retlw		b'01111100'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'01111100'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'01111100'
			retlw		b'00000000'

_FONT_9		;// return font of 9
			movlw		kFntFn_PCLATH
			movwf		PCLATH
			
			movlw		0x0F
			andwf		scany, W
			addwf		PCL, f
			retlw		b'00000000'
			retlw		b'01111100'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'10000110'
			retlw		b'01111110'
			retlw		b'00000110'
			retlw		b'00000110'
			retlw		b'00000110'
			retlw		b'00001100'
			retlw		b'01111000'
			retlw		b'00000000'

_FONT__		;// return font of blank
			movlw		kFntFn_PCLATH
			movwf		PCLATH
			
			movlw		0x0F
			andwf		scany, W
			addwf		PCL, f
			retlw		b'00000000'
			retlw		b'00000000'
			retlw		b'00000000'
			retlw		b'00000000'
			retlw		b'00000000'
			retlw		b'00000000'
			retlw		b'00000000'
			retlw		b'00000000'
			retlw		b'00000000'
			retlw		b'00000000'
			retlw		b'00000000'
			retlw		b'00000000'
			retlw		b'00000000'
			retlw		b'00000000'
			retlw		b'00000000'
			retlw		b'00000000'



;//==========================================================================
;//			END
;//==========================================================================

			end
