; TM1638 (LED&KEY Break out Board)
	cpu	8048
	page	0

; hardware define
STB	EQU	1<<0	;P10
CLK	EQU	1<<1	;P11
DIO	EQU	1<<2	;P12

;TM1638 Control
; display control [1000abbb]	a(1=on/0=off) bbb(000=1/16 ... 111=14/16) 
TM1638_ACTIVE	EQU	8fh	;Display Control ON, Bright 14/16
TM1638_WRINC	EQU	40h	;AutoInc WR
TM1638_WRFIX	EQU	44h	;FixAddress WR
TM1638_BUTTON	EQU	42h	;Button RD
TM1638_TOP	EQU	0c0h	;TM1638 Buffer top

SET_H	macro	NNN
	orl	P1,#NNN
	endm
SET_L	macro	NNN
	anl	P1,#~NNN
	endm
DIO_IN	macro	NNN
	in	a,P1
	anl	a,#NNN
	endm
;-----------------------------------------------------------------------
	org	20h	;internal ram top address
SEGBUF	ds	8	;7Seg data Buffer

	org	0
init:
	SET_H	STB
	SET_H	CLK
	SET_H	DIO

;tm1638 reset
reset:
	mov	R7,#TM1638_ACTIVE	;Display Control ON, 14/16
	SET_L	STB
	call	SCKOUT
	SET_H	STB

	mov	R7,#TM1638_WRINC	;Set Normal,Inc,Write
	SET_L	STB
	call	SCKOUT
	SET_H	STB

;tm1638 all clear
	mov	R7,#TM1638_TOP	;Set top address
	SET_L	STB
	call	SCKOUT
	mov	R1,#16
$$loop	mov	R7,#0
	call	SCKOUT		;all clear
	djnz	R1,$$loop
	SET_H	STB

; SEGBUF Clear
clear:
	mov	R0,#SEGBUF
	mov	R7,#8
	clr	a
$$loop	mov	@R0,a
	inc	R0
	djnz	R7,$$loop

;test patterm HELLO..
testptn:
	mov	R0,#SEGBUF	;buffer top
	mov	R7,#_HELLO	;msg top
$$loop	mov	a,R7
	inc	R7
	movp	a,@a
	jz	$$end
	mov	@R0,a
	inc	R0
	jmp	$$loop
$$end	call	segLed

;demo program.
	mov	R2,#7		;display control 88+R2[b2..b0]
	mov	R0,#SEGBUF+7
	clr	a
	mov	@R0,a
demoloop:
	call	getBtn
	mov	R7,a		;save value.
	xrl	a,@R0		;button == @R0 ?
	jz	demoloop
	mov	a,R7		;restore value.
	mov	@R0,a		;display 7 Seg LED
	call	dotLed		;display 8 Dot LED
	call	segLed
	mov	a,@R0		;restore value.
	jb0	$$push1
	jb1	$$push2
	jmp	demoloop
$$push1	inc	R2
	jmp	$$skip
$$push2	dec	R2
$$skip	mov	a,R2
	anl	a,#7		;save lower 3 bit
	orl	a,#88h
	mov	R7,a
	SET_L	STB		;TM1638 Display Control
	call	SCKOUT
	SET_H	STB
	jmp	demoloop

_HELLO	db	76h, 79h, 38h, 38h, 3fh, 82h, 82h, 0	;HELLO!!

	align	256

; SEGBUFFER to 7SEG transfer 8 bytes
; @input	(SEGBUF ... SEGBUF+7)
; @broken	Acc,R4,R5,R6,R7
segLed:
	mov	a,R0
	mov	R4,a	;save R0
	mov	R5,#0	;counter 0..7
$$loop	mov	a,R5
	rl	a
	add	a,#TM1638_TOP	;Address 7Seg, Left(0) - Right(7) Address=0xc0 + (pos<<1)
	mov	R7,a
	SET_L	STB
	call	SCKOUT
	mov	a,#SEGBUF
	add	a,R5
	mov	R0,a
	mov	a,@R0
	mov	R7,a
	call	SCKOUT
	SET_H	STB
	inc	R5
	mov	a,R5
	add	a,#(256-8)	; check counter < 8
	jnc	$$loop
	mov	a,R4
	mov	R0,a	;restore R0
	ret
	
;button read
; @broken Acc,R5,R6,R7
; @return Acc	(b7 b6 ... b0)
getBtn:
	mov	R5,#0
	mov	R7,#TM1638_BUTTON	;Buttons read
	SET_L	STB
	call	SCKOUT
	SET_H	DIO		;dummy read, change DIO Input mode
	call	SCKIN		;button 5,1
	rr	a
	orl	a,R5
	mov	R5,a
	call	SCKIN		;button 6,2
	rr	a
	rr	a
	orl	a,R5
	mov	R5,a
	call	SCKIN		;button 7,3
	rr	a
	rr	a
	rr	a
	orl	a,R5
	mov	R5,a
	call	SCKIN		;button 8,4
	rr	a
	rr	a
	rr	a
	rr	a
	orl	a,R5
	SET_H	STB
	ret

;led output
; @input Acc	(b7 b6 ... b0)
; @broken Acc,R4,R5,R6,R7

dotLed:
	mov	R5,a		;save work
	mov	R4,#0		;address counter
$$loop	mov	a,R4
	rl	a
	add	a,#0c1h		;Address DotLED Left(0xc1) - Right(0xcf) bit0
	mov	R7,a
	SET_L	STB
	call	SCKOUT
	mov	a,R5
	rl	a
	mov	R5,a
	mov	R7,a
	call	SCKOUT
	SET_H	STB
	mov	a,R4
	inc	a
	mov	R4,a
	add	a,#(256-9)	;check counter < 9
	jnc	$$loop
	ret

; Serial Clock Output (LSB to MSB, Rise CLK)
; @input	R7
; @broken	Acc,R6
SCKOUT:
	mov	R6,#8		;8bit
$$loop	mov	a,R7
	jb0	$$set
	SET_L	DIO
	jmp	$$next
$$set	SET_H	DIO
	jmp	$$next
$$next	SET_L	CLK
	SET_H	CLK		;Clock Low to High
	mov	a,R7
	RR	A
	mov	R7,a
	djnz	R6,$$loop
	ret

; Serial Clock Input
; @broken	Acc,R7,R6
; @return	Acc=R6
SCKIN:
	mov	R6,#0	;work
	mov	R7,#8	;8bit
$$loop	SET_L	CLK
	SET_H	CLK
	DIO_IN	DIO
	jnz	$$set
	mov	a,R6
	jmp	$$next
$$set	mov	a,R6
	orl	a,#1
$$next	rl	a
	mov	R6,a
	djnz	R7,$$loop
	mov	a,R6
	ret

