---
# System prepended metadata

title: '[8051 Tetris 簡報](https://docs.google.com/presentation/d/1pr5QbqixOcwhW0W9klntLjVsDaj4ky8KesqKku3L7Wc/edit?usp=sharing)'
tags: ['8051']

---

# [8051 Tetris 簡報](https://docs.google.com/presentation/d/1pr5QbqixOcwhW0W9klntLjVsDaj4ky8KesqKku3L7Wc/edit?usp=sharing)

###### tags: `8051`

## 1. 7404 (NOT)
![](https://upload.wikimedia.org/wikipedia/commons/f/f4/7404_Hex_Inverters.PNG)

## 2. 7408 (AND)
![](https://upload.wikimedia.org/wikipedia/commons/8/83/QUAD_2-Input_AND_GATE_IC.png)

## 3. 7432 (OR)
![](http://www.alfceliento.com/joomla/images/stories/datasheets/pinout7432.jpg)

## 4. 七段共陽顯示器+7447

## 5. HD74LS283P (全加器)

![](https://i.imgur.com/FCvepjp.png)

## 8051 Tetris Source code

```
	ORG 	0000H
	ljmp	_INIT
;##########################################################################
	ORG	000BH
_TIMER0_ISR:
	cpl 	P1.2
_END_TIMER0_ISR:
	mov	TH0,20H	;reload timer higher byte
	mov	TL0,21H	;reload timer lower byte(0xC350 = 50000)
	reti
;##########################################################################
	ORG 	001BH			; timer 1 interrupt
	MOV 	TH1, 	#00H
	MOV 	TL1, 	#00H
	DJNZ 	R3, 	_CONT		; count 30 times, can get 1s delay
	sjmp	_timer1_TMP
_CONT:
	reti
_timer1_TMP:
	MOV 	R3, 	51h
	; whether need create new block
	setb	2CH.1
	JNB	2CH.0, _Create_block	; if p2.0 == 0
	ljmp	_Drop
;##########################################################################
_game_over_check:
	mov	1FH, 	@R0
	ANL	A, 	@R0
	mov	@R0, 	A
	ADD	A, 	10H
ret
;##########################################################################
_Create_block:
	MOV	42H,	43H
	lcall	_rand
	lcall	_PUT_LCD
	MOV	A,	42H
	CJNE	A, 	#0, 	_init_block1
_init_block0:
	; change the led matrix
	mov	A, 	#11110011B
	mov	R0, 	#30H
	mov	10H, 	#00001100B
	acall	_game_over_check
	CJNE	A, 	1FH,	 _block0_end
	mov	A, 	#11100111B
	mov	R0, 	#31H
	mov	10H, 	#00011000B
	acall	_game_over_check
	CJNE	A, 	1FH,	 _block0_end
	; init shift number	
	mov	04H,  	#0
	mov	05H,  	#0
	; next block state
	mov	13H, 	#0			; rotate sequence number
	mov	14H, 	#11101111B
	mov	15H, 	#11100111B
	mov	16H, 	#11110111B
	; basic	imformation
	PUSH 	PSW
	mov	12H,  	#0		; block sequence number
	mov	PSW, 	#00011000B		; open bank3
	mov	R0, 	#2
	mov	R2, 	#11110011B
	mov	R3, 	#11100111B
	mov	R6, 	#31H		; the bottom row
	POP	PSW
	sjmp	_block0_c
_block0_end:
	setb	2DH.0
_block0_c:
	ljmp	_init_end
_init_block1:
	CJNE	A, 	#1, 	_init_block2
	; change the led matrix
	mov	A, 	#11100111B
	mov	R0, 	#30H
	mov	10H, 	#00011000B
	acall	_game_over_check
	CJNE	A, 	1FH,	 _block1_end
	mov	A, 	#11110011B
	mov	R0, 	#31H
	mov	10H, 	#00001100B
	acall	_game_over_check
	CJNE	A, 	1FH,	 _block1_end
	; init shift number	
	mov	04H,  	#0
	mov	05H,  	#0
	; next block state
	mov	13H, 	#0			; rotate sequence number
	mov	14H, 	#11110111B
	mov	15H, 	#11100111B
	mov	16H, 	#11101111B
	; basic	imformation
	PUSH 	PSW
	mov	12H,  	#1		; block sequence number
	mov	PSW, 	#00011000B		; open bank3
	mov	R0, 	#2
	mov	R2, 	#11100111B
	mov	R3, 	#11110011B
	mov	R6, 	#31H		; the bottom row
	POP	PSW
	sjmp	_block1_c
_block1_end:
	setb	2DH.0
_block1_c:
	ljmp	_init_end
_init_block2:
	CJNE	A, 	#2, 	_init_block3
	; change the led matrix
	mov	A, 	#11100111B
	mov	R0, 	#30H
	mov	10H, 	#00011000B
	acall	_game_over_check
	CJNE	A, 	1FH,	 _block2_end
	mov	A, 	#11100111B
	mov	R0, 	#31H
	mov	10H, 	#00011000B
	acall	_game_over_check
	CJNE	A, 	1FH,	 _block2_end
	; init shift number	
	mov	04H,  	#0
	mov	05H,  	#0
	; basic	imformation
	PUSH 	PSW
	mov	12H,  	#2		; block sequence number
	mov	PSW, 	#00011000B		; open bank3
	mov	R0, 	#2
	mov	R2, 	#11100111B
	mov	R3, 	#11100111B
	mov	R6, 	#31H		; the bottom row
	POP	PSW
	sjmp	_block2_c
_block2_end:
	setb	2DH.0
_block2_c:
	ljmp	_init_end
_init_block3:
	CJNE	A, 	#3,	_init_block4
	; change the led matrix
	mov	A, 	#11111011B
	mov	R0,	#30H
	mov	10H,	#00000100B
	acall	_game_over_check
	CJNE	A, 	1FH,	 _block3_end
	mov	A, 	#11100011B
	mov	R0, 	#31H
	mov	10H, 	#00011100B
	acall	_game_over_check
	CJNE	A, 	1FH,	 _block3_end
	; init shift number	
	mov	04H,  	#0
	mov	05H,  	#0
	; next block state
	mov	13H, 	#0			; rotate sequence number
	mov	14H, 	#11110111B
	mov	15H, 	#11110111B
	mov	16H, 	#11110011B
	; basic	imformation
	PUSH 	PSW
	mov	12H,	#3		; block sequence number
	mov	PSW, 	#00011000B		; open bank3
	mov	R0,  	#2
	mov	R2,  	#11111011B
	mov	R3,  	#11100011B
	mov	R6,  	#31H		; the bottom row
	POP	PSW	
	sjmp	_block3_c
_block3_end:
	setb	2DH.0
_block3_c:
	ljmp	_init_end
_init_block4:
	CJNE	A, 	#4, 	_init_block5
	; change the led matrix
	mov	A, 	#11101111B
	mov	R0, 	#30H
	mov	10H, 	#00010000B
	acall	_game_over_check
	CJNE	A, 	1FH,	 _block4_end
	mov	A, 	#11100011B
	mov	R0, 	#31H
	mov	10H, 	#00011100B
	acall	_game_over_check
	CJNE	A, 	1FH,	 _block4_end
	; init shift number	
	mov	04H,  	#0
	mov	05H,  	#0
	; next block state
	mov	13H, 	#0			; rotate sequence number
	mov	14H, 	#11110011B
	mov	15H, 	#11110111B
	mov	16H, 	#11110111B
	; basic	imformation
	PUSH 	PSW
	mov	12H,  	#4		; block sequence number
	mov	PSW, 	#00011000B		; open bank3
	mov	R0, 	#2
	mov	R2, 	#11101111B
	mov	R3, 	#11100011B
	mov	R6, 	#31H		; the bottom row
	POP	PSW	
	sjmp	_block4_c
_block4_end:
	setb	2DH.0
_block4_c:
	ljmp	_init_end
_init_block5:
	CJNE	A, 	#5, 	_init_block6
	; change the led matrix
	mov	A, 	#11110111B
	mov	R0, 	#30H
	mov	10H, 	#00001000B
	acall	_game_over_check
	CJNE	A, 	1FH,	 _block5_end
	mov	A, 	#11100011B
	mov	R0, 	#31H
	mov	10H, 	#00011100B
	acall	_game_over_check
	CJNE	A, 	1FH,	 _block5_end
	; init shift number	
	mov	04H,  	#0
	mov	05H,  	#0
	; next block state
	mov	13H, 	#0			; rotate sequence number
	mov	14H, 	#11110111B
	mov	15H, 	#11110011B
	mov	16H, 	#11110111B
	; basic	imformation
	PUSH 	PSW
	mov	12H,  	#5		; block sequence number
	mov	PSW, 	#00011000B		; open bank3
	mov	R0, 	#2
	mov	R2, 	#11110111B
	mov	R3, 	#11100011B
	mov	R6, 	#31H		; the bottom row
	POP	PSW	
	sjmp	_block5_c
_block5_end:
	setb	2DH.0
_block5_c:
	ljmp	_init_end
_init_block6:
	; change the led matrix
	mov	A, 	#11000011B
	mov	R0, 	#30H
	mov	10H, 	#00111100B
	acall	_game_over_check
	CJNE	A, 	1FH,	 _block6_end
	; init shift number	
	mov	04H,  	#0
	mov	05H,  	#0
	; next block state
	mov	13H, 	#0			; rotate sequence number
	mov	14H, 	#11110111B
	mov	15H, 	#11110111B
	mov	16H, 	#11110111B
	mov	17H, 	#11110111B
	; basic	imformation
	PUSH 	PSW
	mov	12H,  	#6		; block sequence number
	mov	PSW, 	#00011000B		; open bank3
	mov	R0, 	#1
	mov	R2, 	#11000011B
	mov	R6, 	#30H		; the bottom row
	POP	PSW
	sjmp	_init_end
_block6_end:
	setb	2DH.0
_init_end:
	; return
	setb	2CH.0			; droping block is existence
	reti
;##########################################################################
_Drop:
	mov	PSW, 	#00011000B		; open bank3
_one:
	CJNE	R0, 	#1, _two
	; ensure the block whether arrive matrix's bottom
	; row1
	mov	A, 	R6
	inc	A
	cjne	A, 	#40H, 	_one_t		; is at the bottom?
	ljmp	_touch			
_one_t:
	; ensure the block whether touch
	; row2
	mov	10H, 	R2
	acall	_Detect_bottom
	CJNE	A, 	1FH, 	_one_J1		; if A != next state, touch. don't mov down
	sjmp	_one_C1
_one_J1:	
	ljmp	_touch
_one_C1:
	; start move down
	; row1
	mov	A, 	R6
	inc	A 
	mov	10H, 	R2
	acall 	_move_bot		; input A is address
	; recover row1
	mov	10H, 	R2
	mov	A, 	R6
	acall	_recover_top
	; end
	mov	A, 	R6
	INC	A
	mov	R6,	A
	mov	R0, 	#1
	ljmp	_drop_end
;##########################################################################
_two:
	CJNE	R0, 	#2, 	_three
	; ensure the block whether arrive matrix's bottom
	; row2
	mov	A, 	R6
	inc	A
	cjne	A, 	#40H, 	_two_t		; is at the bottom?
	ljmp	_touch			
_two_t:
	; ensure the block whether touch
	; row2
	mov	10H, 	R3
	acall	_Detect_bottom
	CJNE	A, 	1FH, 	J1		; if A != next state, touch. don't mov down
	sjmp	C1
J1:	ljmp	_touch
C1:
	; row1
	mov	A, 	R6
	mov	10H, 	R2			; input (R2 is now row , r3 is next row, r6 is bottom address), output A
	mov	11H, 	R3
	acall	_Detect_mid
	CJNE	A, 	1FH, 	J2		; if A != next state(1FH, BANK3's R7), touch. don't mov down
	sjmp	C2
J2:	ljmp	_touch
C2:
	; start move down
	; row2
	mov	A, 	R6
	inc	A 
	mov	10H, 	R3
	acall 	_move_bot		; input A is address
	; row1
	mov	10H, 	R2
	mov	11H, 	R3
	mov	A, 	R6
	acall	_move_mid		; input (10h is now row , 11h is next row, r6 is bottom address)
	; recover row1
	mov	10H, 	R2
	mov	A, 	R6
	dec	A
	acall	_recover_top
	; end
	mov	A, 	R6
	INC	A
	mov	R6, 	A
	mov	R0, 	#2
	ljmp	_drop_end
;##########################################################################
_three:
	CJNE	R0, 	#3, 	_four
	; ensure the block whether arrive matrix's bottom
	; row3
	mov	A, 	R6
	inc	A
	cjne	A, 	#40H, 	_three_t		; is at the bottom?
	ljmp	_touch			
_three_t:
	; ensure the block whether touch
	; row3
	mov	10H, 	R4
	acall	_Detect_bottom
	CJNE	A, 	1FH, 	_three_j1		; if A != next state(1FH, BANK3's R7), touch. don't mov down
	sjmp	_three_c1
_three_j1:
	ljmp	_touch
_three_c1:
	; row2
	mov	A, 	R6
	mov	10H, 	R3			; input (R2 is now row , r3 is next row, r6 is bottom address), output A
	mov	11H, 	R4
	acall	_Detect_mid
	CJNE	A, 	1FH, 	_three_j2		; if A != next state(1FH, BANK3's R7), touch. don't mov down
	sjmp	_three_c2
_three_j2:
	ljmp	_touch
_three_c2:
	; row1
	mov	A, 	R6
	dec	A
	mov	10H, 	R2			; input (R2 is now row , r3 is next row, r6 is bottom address), output A
	mov	11H, 	R3
	acall	_Detect_mid
	CJNE	A, 	1FH, 	_three_j3		; if A != next state(1FH, BANK3's R7), touch. don't mov down
	sjmp	_three_c3
_three_j3:
	ljmp	_touch
_three_c3:
	; start move down
	; row3
	mov	A, 	R6
	inc	A 
	mov	10H, 	R4
	acall 	_move_bot		; input A is address
	; row2
	mov	10H, 	R3
	mov	11H, 	R4
	mov	A, 	R6
	acall	_move_mid		; input (10h is now row , 11h is next row, r6 is bottom address)
	; row1
	mov	10H, 	R2
	mov	11H, 	R3
	mov	A, 	R6
	dec	A
	acall	_move_mid		; input (10h is now row , 11h is next row, r6 is bottom address)
	; recover row1
	mov	10H, 	R2
	mov	A, 	R6
	dec	A
	dec	A
	acall	_recover_top
	; end
	mov	A, 	R6
	INC	A
	mov	R6, 	A
	mov	R0, 	#3
	ljmp	_drop_end
;##########################################################################	
_four:
	; ensure the block whether arrive matrix's bottom
	; row1
	mov	A, 	R6
	inc	A
	cjne	A, 	#40H, 	_four_t		; is at the bottom?
	ljmp	_touch			
_four_t:
	; ensure the block whether touch
	; row4
	mov	10H, 	R5
	acall	_Detect_bottom
	CJNE	A, 	1FH, 	_touch		; if A != next state(1FH, BANK3's R7), touch. don't mov down
	; start move down
	; row4
	mov	A, 	R6
	inc	A 
	mov	10H, 	R5
	acall 	_move_bot		; input A is address
	; row3
	mov	A, 	R6 
	mov	10H, 	R4
	mov	11H, 	R5
	acall 	_move_mid		; input A is address
	; row2
	mov	A, 	R6
	dec	A 
	mov	10H, 	R3
	mov	11H, 	R4
	acall 	_move_mid		; input A is address
	; row1
	mov	A, 	R6
	subb	A, 	#2
	mov	10H, 	R2
	mov	11H, 	R3
	acall 	_move_mid		; input A is address
	; recover row1
	mov	10H, 	R2
	mov	A, 	R6
	subb	A, 	#3
	acall	_recover_top
	; end
	mov	A, 	R6
	INC	A
	mov	R6, 	A
	mov	R0, 	#4
	sjmp	_drop_end
;##########################################################################
_touch:
	mov	PSW, 	#00010000B		; BANK 2
	mov	R0, 	#3FH
_is_elimate:
	mov	A, 	@R0
	cjne	A, 	#00000000B, _c
	; _elimate_start
	inc	28h
	mov	A, 	R0
	mov	19H, 	A			; 19h tmp use
	mov	R1, 	A
	_down_loop:
		dec	R1
		mov	A, 	@R1		; previos row
		INC	R1
		mov	@R1, 	A		; for now row	
	DEC	R1
	CJNE 	R1, 	#30H, 	_down_loop
	mov	30H, 	#11111111B
	mov	A, 	19H
	mov	R0, 	A
	sjmp	_is_elimate		; maybe has two or more row need to be eliminate, so check again
	; _elimate_end
	_c:	
	DEC	R0
CJNE 	R0, 	#2FH, 	_is_elimate	; exceed the 30h

	clr	2CH.0
	lcall	_Speed_up
	lcall	_PUT_LCD
	sjmp	_drop_end
;##########################################################################
_drop_end:
	mov	PSW, 	#00000000B
	; end code section
	JB	2CH.1, 	_intterupt
	ret
_intterupt:
	mov	PSW, 	#00000000B
	clr	2CH.1
	RETI
;##########################################################################
_Detect_bottom:; A, 10H input ; A output ; 42H R1 R7 tmp use
	mov	R1, 	A
	mov	A, 	@R1			
	mov	R7, 	A			; the next row state
	ANL	A, 	10H
	mov	42H, 	A
	mov	A, 	10H
	CPL	A
	ADD	A, 	42H
ret
_Detect_mid:; A, 10H 11H input ; A output ; 42H R1 R7 tmp use
	mov	R1, 	A
	mov	A, 	@R1
	mov	42H, 	A
	mov	A, 	11H
	CPL	A
	ADD	A, 	42H
	mov	R7, 	A			; next state, exclude the droping block
	ANL	A, 	10H
	mov	42H, 	A
	mov	A, 	10H
	CPL	A
	ADD	A, 	42H
ret
;##########################################################################
_move_bot:	;A is next row address
	mov	R1, 	A
	mov	A, 	@R1			; the (bottom + 1) row state
	ANL	A, 	10H
	mov	@R1, 	A
ret
_move_mid:;  A(next row address), 10H(move row) 11H(next row) input ; A output ; 42H R1 R7 tmp use
	mov	R1, 	A
	mov	A, 	@R1
	mov	42H, 	A
	mov	A, 	11H
	CPL	A
	ADD	A, 	42H
	ANL	A, 	10H
	mov	@R1, 	A
ret
_recover_top:	;10H input
	mov	R1, 	A
	mov	A, 	@R1
	mov	42H, 	A
	mov	A, 	10H
	CPL	A
	ADD	A, 	42H
	mov	@R1,	A
ret
;##########################################################################
_rand:
	mov	A,	2AH
	CJNE	A, 	#127, 	_KEEP
	mov	2AH, 	#0
 _KEEP:
	mov	A, 	41H
	mov	B, 	#7
	div	AB
	mov	A,	B
	
	CJNE	A, 	#0, 	_r1
	JB	2AH.0, 		_r7
	setb	2AH.0
	SJMP	_end_rand
_r1:
	CJNE	A, 	#1, 	_r2
	JB	2AH.1, 		_r7
	setb	2AH.1
	SJMP	_end_rand
_r2:
	CJNE	A, 	#2, 	_r3
	JB	2AH.2, 		_r7
	setb	2AH.2
	SJMP	_end_rand
_r3:
	CJNE	A, 	#3, 	_r4
	JB	2AH.3, 		_r7
	setb	2AH.3
	SJMP	_end_rand
_r4:
	CJNE	A, 	#4, 	_r5
	JB	2AH.4, 		_r7
	setb	2AH.4
	SJMP	_end_rand
_r5:
	CJNE	A, 	#5, 	_r6
	JB	2AH.5, 		_r7
	setb	2AH.5
	SJMP	_end_rand
_r6:
	CJNE	A, 	#6, 	_r7
	JB	2AH.6, 		_r7
	setb	2AH.6
	SJMP	_end_rand
_r7:
	mov	A,	41H
	add	A,	#8
	mov	41H,	A
	SJMP	_rand
_end_rand:
	MOV	43H, 	A
	ret

;##########################################################################


	; p0 row
	; p1 col	EX: 20H include c1~c8 at row1
	; 68H has no drop shape
	
	; bank 0
	; R1 scanner use
	; R2 row current provide
	; R3 timer_interrupt use
	; R5 sum of shift left	(04H)
	; R6 sum of shift right	(05H)
	; R7 timer_delay use
	
	; bank 2
	; 10h, 11h  function parameter
	; 12h block seq
	; 13h rotate num
	; 14h, 15h, 16h, 17h next block state
	
	; bank 3
	; store the droping block imformation
	
	; memory
	; 20h~27h   timer2 use
	; 28h	score
	; 29h	game mode
	; 2Ah	block counter
	; 2Bh.0	music choice flag
	; 2Dh.0 gameover flag
	; 30h~40h for led matrix 
	; 41h random variable
	; 42h temp use
	; 43h next block
	; 2CH.0 has droping block
	; 2CH.1 in the intterupt
	; 51h 	speed
	; 52h~55h	rotate tmp register
	; 56h~57h	delay
	; 58h	music speed
	
;##########################################################################
	ORG	0410H
_INIT:
	clr	TR1
	mov	TMOD, 	#11H
	;lcall 	_TIMER_DELAY
	mov	IE,   	#8AH		; enabke Timer1.0 intterupt
	mov	TH0,  	#0C3H		;set timer higher byte
	mov	TL0,  	#50H		;set timer lower byte(0xC350 = 50000)
	mov	20H,  	#0ffH		;reload timer higher byte
	mov	21H,  	#50H		;reload timer lower byte(0xC350 = 50000)
	mov	22H,  	#0
	mov	23H,  	#1
	mov	24H,  	#1
	mov	25H,  	#1
	mov	26H,	#0
	mov	27H,	#0FFH
	
	mov	28H,	#0		;Score
	mov	29H,	#0		;Level
	CLR	2BH.0
	
	mov	30H,  	#11111111B	; c1~c8 at row1
	mov	31H,  	#11111111B	; c1~c8 at row2
	mov	32H,  	#11111111B	; c1~c8 at row3
	mov	33H,  	#11111111B	; c1~c8 at row4
	mov	34H,  	#11111111B	; c1~c8 at row5
	mov	35H,  	#11111111B	; c1~c8 at row6
	mov	36H,  	#11111111B	; c1~c8 at row7
	mov	37H,  	#11111111B	; c1~c8 at row8
	mov	38H,  	#11111111B	; c1~c8 at row9
	mov	39H,  	#11111111B	; c1~c8 at row10
	mov	3AH,  	#11111111B	; c1~c8 at row11
	mov	3BH,  	#11111111B	; c1~c8 at row12
	mov	3CH,  	#11111111B	; c1~c8 at row13
	mov	3DH,  	#11111111B	; c1~c8 at row14
	mov	3EH,  	#11111111B	; c1~c8 at row15
	mov	3FH,  	#11111111B	; c1~c8 at row16
	
	lcall	_INIT_LCD
	mov	41H,	#0
	mov	2AH,	#00000001B
	lcall	_rand
	mov	50h,	#1
	mov	51h,	#30
	mov	58h,	#6
	mov	60h,	#30
	mov	61h,	#30
	
	clr	2DH.0
	clr	2CH.0
	clr	2CH.1
	MOV	R1, #30H
	MOV	R2, #00000000B 	
	MOV 	R3,   	51h
	MOV 	DPTR, 	#0A001H
	MOV 	TH1, 	#00H
	MOV 	TL1, 	#00H
	lcall	_PUT_LCD
	setb	TR0
	setb	TR1
;##########################################################################
_Main:
	JB	2Dh.0,	_Game_over
	lcall 	_LED_SCANNER
	JNB	2CH.0, 	_Main		; because no droping block, don't receive S1~S4
	MOV 	DPTR, 	#0A001H
	movx	A, 	@DPTR
	cjne 	A, 	#11111111B, 	_S1
	sjmp	_Main
;##########################################################################
_Game_over:
	CLR	TR1
	mov	58H,	#7
	mov	23H,	#1
	mov	24H,	#1
	mov	25H,	#1
	SETB	2BH.0
	mov	22H,	#0
	lcall 	_SOUND
	mov	60h,	#30
	mov	61h,	#30
	mov	PSW,	#00000000B
	mov	30H,	#11111111B	; c1~c8 at row1
	mov	31H,	#10000001B	; c1~c8 at row2
	mov	32H,	#10111111B	; c1~c8 at row3
	mov	33H,	#10111111B	; c1~c8 at row4
	mov	34H,	#10100001B	; c1~c8 at row5
	mov	35H,	#10111011B	; c1~c8 at row6
	mov	36H,	#10000011B	; c1~c8 at row7
	mov	37H,	#11111111B	; c1~c8 at row8
	mov	38H,  	#11111111B	; c1~c8 at row9
	mov	39H,  	#10000001B	; c1~c8 at row10
	mov	3AH,  	#10111111B	; c1~c8 at row11
	mov	3BH,  	#10111111B	; c1~c8 at row12
	mov	3CH,  	#10100001B	; c1~c8 at row13
	mov	3DH,  	#10111011B	; c1~c8 at row14
	mov	3EH,  	#10000011B 	; c1~c8 at row15
	mov	3FH,  	#11111111B	; c1~c8 at row16
	_over_loop:
		SETB	2BH.0
		lcall 	_LED_SCANNER
	sjmp	_over_loop
;##########################################################################

_s1:
	cjne 	A, 	#11111110B, 	_S2
	mov	A,	41H
	add	A,	#8
	mov	41H,	A
	clr	TR1
	lcall	_Rotate
	mov	PSW, 	#00000000B
	mov	R0, 	#10
	setb	TR1
_wait_s1:
	lcall   _LED_SCANNER
	djnz	R0, 	_wait_s1
	ljmp	_Main
;##########################################################################
_s2:
	cjne 	A, 	#11111101B, 	_s3
	mov	A,	41H
	add	A,	#8
	mov	41H,	A
	clr	TR1
	lcall	_block_left
	; wait
	mov	PSW, 	#00000000B
	mov	R0, 	#10
	setb	TR1	
_wait_s2:
	lcall   _LED_SCANNER
	djnz	R0,	_wait_s2
	ljmp	_Main
;##########################################################################
_s3:
	cjne 	A, 	#11111011B, 	_s4
	mov	A,	41H
	add	A,	#8
	mov	41H,	A
	clr	TR1
	lcall	_Drop
	mov	PSW, 	#00000000B
	mov	R0, 	#5
	setb	TR1
_wait_s3:
	lcall   _LED_SCANNER
	djnz	R0, 	_wait_s3
	ljmp	_Main	
_s4:
	clr	TR1
	mov	A,	41H
	add	A,	#8
	mov	41H,	A
	lcall	_block_right
	mov	PSW, 	#00000000B
	mov	R0, 	#10
_wait_s4:
	lcall   _LED_SCANNER
	djnz	R0, 	_wait_s4
	setb	TR1
	ljmp	_Main	
	
;############################################################################
_SOUND:
	djnz	23H, _END_MELODY_I
	djnz	24H, _END_MELODY_J
	djnz	25H, _END_MELODY_K
	sjmp	_IN_MELODY
_START_MELODY:
	mov	22H, #0
_IN_MELODY:
	mov	A,22H
	JB	2BH.0,	_ED_H		
	mov	dptr, #MELODY
	SJMP	_END_H
	_ED_H:
	mov	dptr, #ED_MELODY
	_END_H:
	movc	A,@A+dptr
	jz	_START_MELODY   ; if the melody is finished start over
	rl	A
	push	ACC		; save ACC value -- we need the register
	mov	dptr, #TONES
	movc	A, @A+dptr
	mov	20H, A
	pop	ACC
	inc	ACC
	movc	A, @A+dptr
	mov	21H, A
	inc	22H              ; next value on the list (length of tone) 
	mov	A,22H
	JB	2BH.0, _ED_L
	mov	dptr, #MELODY
	SJMP	_END_L
	_ED_L:
	mov	dptr, #ED_MELODY
	_END_L:
	movc	A,@A+dptr
	mov	25H, A
 	inc	22H		; and the next value
_END_MELODY_K:
	mov	24H, #7
_END_MELODY_J:
	mov	23H, 58H
_END_MELODY_I:
ret

;##########################################################################

_Speed_up:
	mov	A,	29H
	CJNE	A,	#0,	_level_1
_level_0:
	mov	A,	28H
	clr	c
	subb	A,	#10
	JC	_level_end
	mov	51H,	#25
	mov	29H,	#1
	mov	58H,	#6
ret
_level_1:
	CJNE	A,	#1,	_level_2
	mov	A,	28H
	clr	c
	subb	A,	#30
	JC	_level_end
	mov	51H,	#20
	mov	29H,	#2
	mov	58H,	#5
ret
_level_2:
	mov	A,	28H
	clr	c
	subb	A,	#50
	JC	_level_end
	mov	51H,	#10
	mov	29H,	#3
	mov	58H,	#4
ret
_level_end:
ret

;##########################################################################
_block_left:
	mov	PSW, 	#00011000B		; open bank3
	CJNE	R0, 	#1, 	_lf_2
_lf_1:
	; detect margin
	; row1
	mov	10H, 	R2
	lcall	_left_check_margin
	JNC	_lf_1_error
	; detect whether touch
	mov	A, 	R6
	mov	11H, 	R2
	lcall	_detect_lf_touch
	CJNE	A, 1FH, _lf_1_error
	sjmp	_lf_1_swift
_lf_1_error:
	ret
_lf_1_swift:	
	; START SWIFT
	; row1
	mov	A, 	R6
	mov	10H, 	R2
	lcall	_row_left
	mov	R2, 	10H
	mov	R0, 	#1
	ljmp	_lf_end
_lf_2:	
	CJNE	R0, 	#2, 	_lf_3
	; detect margin
	mov	10H, 	R2
	lcall	_left_check_margin
	JNC	_lf_2_error
	mov	10H, 	R3
	lcall	_left_check_margin
	JNC	_lf_2_error
	; detect whether touch
	mov	A, 	R6
	mov	11H, 	R3
	lcall	_detect_lf_touch
	CJNE	A, 	1FH, 	_lf_2_error		; if A != next state(1FH, BANK3's R7), touch. don't mov down
	mov	A, 	R6
	dec	A
	mov	11H, 	R2
	lcall	_detect_lf_touch
	CJNE	A, 	1FH, 	_lf_2_error		; if A != next state(1FH, BANK3's R7), touch. don't mov down
	sjmp	_lf_2_swift
_lf_2_error:
	ret
_lf_2_swift:
	; start shift left
	; row2
	mov	A, 	R6
	mov	10H, 	R3
	lcall	_row_left
	mov	R3, 	10H
	; row1
	mov	A, 	R6
	dec	A
	mov	10H, 	R2
	lcall	_row_left
	mov	R2, 	10H
	ljmp	_lf_end
_lf_3:
	CJNE	R0, 	#3, 	_lf_4
	; detect margin
	mov	10H, 	R2
	lcall	_left_check_margin
	JNC	_lf_3_error
	mov	10H, 	R3
	lcall	_left_check_margin
	JNC	_lf_3_error
	mov	10H, 	R4
	lcall	_left_check_margin
	JNC	_lf_3_error
	; detect whether touch
	mov	A, 	R6
	mov	11H, 	R4
	lcall	_detect_lf_touch
	CJNE	A, 	1FH, 	_lf_3_error		; if A != next state(1FH, BANK3's R7), touch. don't mov down
	mov	A, 	R6
	dec	A
	mov	11H, 	R3
	lcall	_detect_lf_touch
	CJNE	A, 1FH, _lf_3_error		; if A != next state(1FH, BANK3's R7), touch. don't mov down
	mov	A, 	R6
	subb	A, 	#2
	mov	11H, 	R2
	lcall	_detect_lf_touch
	CJNE	A, 	1FH, 	_lf_3_error		; if A != next state(1FH, BANK3's R7), touch. don't mov down
	sjmp	_lf_3_swift
_lf_3_error:
	ret
_lf_3_swift:
	; start shift left
	; row3
	mov	A, 	R6
	mov	10H, 	R4
	lcall	_row_left
	mov	R4, 	10H
	; row2
	mov	A, 	R6
	dec	A
	mov	10H, 	R3
	lcall	_row_left
	mov	R3, 	10H
	; row1
	mov	A, 	R6
	dec	A
	dec	A
	mov	10H, 	R2
	lcall	_row_left
	mov	R2, 	10H
	mov	R0, 	#3
	ljmp	_lf_end
_lf_4:
	CJNE	R0, 	#4, 	_lf_4_error
	; detect margin
	mov	10H, 	R2
	lcall	_left_check_margin
	JNC	_lf_4_error
	; detect whether touch
	mov	A, 	R6
	mov	11H, 	R5
	lcall	_detect_lf_touch
	CJNE	A, 	1FH, 	_lf_4_error		; if A != next state(1FH, BANK3's R7), touch. don't mov down
	mov	A, 	R6
	dec	A
	mov	11H, 	R4
	lcall	_detect_lf_touch
	CJNE	A, 1FH, _lf_4_error		; if A != next state(1FH, BANK3's R7), touch. don't mov down
	mov	A, 	R6
	subb	A, 	#2
	mov	11H, 	R3
	lcall	_detect_lf_touch
	CJNE	A, 	1FH, 	_lf_4_error		; if A != next state(1FH, BANK3's R7), touch. don't mov down
	mov	A, 	R6
	subb	A, 	#3
	mov	11H, 	R2
	lcall	_detect_lf_touch
	CJNE	A, 	1FH, 	_lf_4_error		; if A != next state(1FH, BANK3's R7), touch. don't mov down
	sjmp	_lf_4_swift
_lf_4_error:
	ret
_lf_4_swift:
	; start shift left
	; row4
	mov	A, 	R6
	mov	10H, 	R5
	lcall	_row_left
	mov	R5, 	10H
	; row3
	mov	A, 	R6
	dec	A
	mov	10H, 	R4
	lcall	_row_left
	mov	R4, 	10H
	; row2
	mov	A, 	R6
	subb	A, 	#2
	mov	10H, 	R3
	lcall	_row_left
	mov	R3, 	10H
	; row1
	mov	A, 	R6
	subb	A, 	#3
	mov	10H, 	R2
	lcall	_row_left
	mov	R2, 	10H
	mov	R0, 	#4
_lf_end:
	inc	04H
ret
;##########################################################################
_left_check_margin:
	setb	C
	mov	A, 10H
	RLC	A
ret
;##########################################################################
_detect_lf_touch:
	lcall	_recover_init
	mov	R1, 	A
	mov	A, 	11H
	RL	A
	mov	R7, 	A
	mov	A, 	R1
	ANL	A, 	R7
	mov	42H, 	A
	mov	A, 	R1
	CPL	A
	ADD	A, 	42H
ret
;##########################################################################
_row_left:
	mov	R1, 	A
	mov	A, 	@R1
	mov	42H, 	A
	mov	A, 	10H
	CPL	A
	ADD	A, 	42H
	mov	42H, 	A
	mov	A, 	10H
	RL	A
	mov	10H, 	A
	ANL	A, 	42H
	mov	@R1, 	A
ret
;##########################################################################
_block_right:
	mov	PSW, 	#00011000B		; open bank3
	CJNE	R0, 	#1, 	_rt_2
_rt_1:
	; detect margin
	mov	10H, 	R2
	lcall	_right_check_margin
	JNC	_rt_1_error
	; detect whether touch
	mov	A, 	R6
	mov	11H, 	R2
	lcall	_detect_rt_touch
	CJNE	A, 1FH, _rt_1_error
	sjmp	_rt_1_swift
_rt_1_error:
	ret
_rt_1_swift:	
	; start shift left
	; row2
	mov	A, 	R6
	mov	10H, 	R2
	lcall	_row_right
	mov	R2, 	10H
	ljmp	_right_end
_rt_2:	
	CJNE	R0, 	#2, 	_rt_3
	; detect margin
	mov	10H, 	R2
	lcall	_right_check_margin
	JNC	_rt_2_error
	mov	10H, 	R3
	lcall	_right_check_margin
	JNC	_rt_2_error
	; detect whether touch
	mov	A, 	R6
	mov	11H, 	R3
	lcall	_detect_rt_touch
	CJNE	A, 	1FH, 	_rt_2_error		; if A != next state(1FH, BANK3's R7), touch. don't mov down
	mov	A, 	R6
	dec	A
	mov	11H, 	R2
	lcall	_detect_rt_touch
	CJNE	A, 	1FH, 	_rt_2_error		; if A != next state(1FH, BANK3's R7), touch. don't mov down
	sjmp	_rt_2_swift
_rt_2_error:
	ret
_rt_2_swift:	
	; start shift left
	; row2
	mov	A, 	R6
	mov	10H, 	R3
	lcall	_row_right
	mov	R3, 	10H
	; row1
	mov	A, 	R6
	dec	A
	mov	10H, 	R2
	lcall	_row_right
	mov	R2, 	10H
	mov	R0, 	#2
	ljmp	_right_end
_rt_3:
	CJNE	R0, 	#3, 	_rt_4
	; detect margin
	mov	10H, 	R2
	lcall	_right_check_margin
	JNC	_rt_3_error
	mov	10H, 	R3
	lcall	_right_check_margin
	JNC	_rt_3_error
	mov	10H, 	R4
	lcall	_right_check_margin
	JNC	_rt_3_error
	; detect whether touch
	mov	A, 	R6
	mov	11H, 	R4
	lcall	_detect_rt_touch
	CJNE	A, 	1FH, 	_rt_3_error		; if A != next state(1FH, BANK3's R7), touch. don't mov down
	mov	A, 	R6
	dec	A
	mov	11H, 	R3
	lcall	_detect_rt_touch
	CJNE	A, 	1FH, 	_rt_3_error		; if A != next state(1FH, BANK3's R7), touch. don't mov down
	mov	A, 	R6
	subb	A,	#2
	mov	11H, 	R2
	lcall	_detect_rt_touch
	CJNE	A, 	1FH, 	_rt_3_error		; if A != next state(1FH, BANK3's R7), touch. don't mov down
	sjmp	_rt_3_swift
_rt_3_error:
	ret
_rt_3_swift:	
	; start shift left
	; row3
	mov	A, 	R6
	mov	10H, 	R4
	lcall	_row_right
	mov	R4, 	10H
	; row2
	mov	A, 	R6
	dec	A
	mov	10H, 	R3
	lcall	_row_right
	mov	R3, 	10H
	; row1
	mov	A, 	R6
	subb	A, 	#2
	mov	10H, 	R2
	lcall	_row_right
	mov	R2, 	10H
	mov	R0, 	#3
	ljmp	_right_end
_rt_4:
	CJNE	R0, 	#4, 	_right_end
	; detect margin
	mov	10H, 	R2
	lcall	_right_check_margin
	JNC	_rt_4_error
	; detect whether touch
	mov	A, 	R6
	mov	11H, 	R4
	lcall	_detect_rt_touch
	CJNE	A, 	1FH, 	_rt_4_error		; if A != next state(1FH, BANK3's R7), touch. don't mov down
	mov	A, 	R6
	dec	A
	mov	11H, 	R3
	lcall	_detect_rt_touch
	CJNE	A, 	1FH, 	_rt_4_error		; if A != next state(1FH, BANK3's R7), touch. don't mov down
	mov	A, 	R6
	subb	A,	#2
	mov	11H, 	R2
	lcall	_detect_rt_touch
	CJNE	A, 	1FH, 	_rt_4_error		; if A != next state(1FH, BANK3's R7), touch. don't mov down
	mov	A, 	R6
	subb	A,	#3
	mov	11H, 	R2
	lcall	_detect_rt_touch
	CJNE	A, 	1FH, 	_rt_4_error		; if A != next state(1FH, BANK3's R7), touch. don't mov down
	sjmp	_rt_4_swift
_rt_4_error:
	ret
_rt_4_swift:	
	; start shift left
	; row4
	mov	A, 	R6
	mov	10H, 	R5
	lcall	_row_right
	mov	R5, 	10H
	; row3
	mov	A, 	R6
	dec	A
	mov	10H, 	R4
	lcall	_row_right
	mov	R4, 	10H
	; row2
	mov	A, 	R6
	subb	A, 	#2
	mov	10H, 	R3
	lcall	_row_right
	mov	R3, 	10H
	; row1
	mov	A, 	R6
	subb	A, 	#3
	mov	10H, 	R2
	lcall	_row_right
	mov	R2, 	10H
	mov	R0, 	#4
	ljmp	_right_end
_right_end:
	inc	05H
ret
;##########################################################################
_right_check_margin:
	setb	C
	mov	A, 10H
	RRC	A
ret
;##########################################################################
_detect_rt_touch:
	lcall	_recover_init
	mov	R1, 	A
	mov	A, 	11H
	RR	A
	mov	R7, 	A
	mov	A, 	R1
	ANL	A, 	R7
	mov	42H, 	A
	mov	A, 	R1
	CPL	A
	ADD	A, 	42H
ret
;##########################################################################
_row_right:
	mov	R1, 	A
	mov	A, 	@R1
	mov	42H, 	A
	mov	A, 	10H
	CPL	A
	ADD	A, 	42H
	mov	42H, 	A
	mov	A, 	10H
	RR	A
	mov	10H, 	A
	ANL	A, 	42H
	mov	@R1, 	A
ret
;##########################################################################
_Rotate:
	mov	PSW, 	#00011000B		; open bank3
	lcall	_adjust_swift
	mov	A, 	R0
	CJNE	A, 	#2, 	_r_hei3
_r_hei2:
	lcall	_rotate_height_2
	ret
_r_hei3:
	CJNE	A, 	#3, 	_r_hei_1or4
	lcall	_rotate_height_3
	ret
_r_hei_1or4:
	lcall	_rotate_height_1or4
	ret
;##########################################################################
_rotate_height_2:
	mov	A, 	R6
	CJNE	A, 	#31H, 	_rotate_height_2_c
	ljmp	_rotate_height_2_error
_rotate_height_2_c:
	mov	A,	12H
	CJNE	A,	#2,	_rotate_height_2_c1
	ret
_rotate_height_2_c1:
	; detect touch
	;row 3
	mov	A, 	R6
	mov	11H, 	R3
	mov	10H,	16H
	lcall	_rotate_touch_detect
	CJNE	A,	1FH,	_rotate_height_2_error
	;row 2
	mov	A, 	R6
	dec	A
	mov	11H, 	R2
	mov	10H,	15H
	lcall	_rotate_touch_detect
	CJNE	A,	1FH,	_rotate_height_2_error
	;row 1
	mov	A, 	R6
	subb	A,	#2
	mov	11H, 	#11111111B
	mov	10H,	14H
	lcall	_rotate_touch_detect
	CJNE	A,	1FH,	_rotate_height_2_error
	sjmp	_rotate_height_2_c2
_rotate_height_2_error:				; because no rotate success, don't adjust_swift again, will change the next state again
	mov	14h,	52h
	mov	15h,	53h
	mov	16h,	54h		
	ret
_rotate_height_2_c2:
	; start rotate
	;row 3
	mov	A, 	R6
	mov	11H, 	R3
	lcall	_recover_init
	ANL	A, 	16H
	mov	@R1, 	A
	;row 2
	mov	A, 	R6
	dec	A
	mov	11H, 	R2
	lcall	_recover_init
	ANL	A, 	15H
	mov	@R1, 	A
	;row 1
	mov	A, 	R6
	subb	A,	#2
	mov	R1, 	A
	mov	A, 	@R1
	ANL	A, 	14H
	mov	@R1, 	A
	; jump to block number
	mov	A, 	12H
	CJNE	A, 	#0, 	h2_b1
_b0:
	; reset now state
	mov	R0, 	#3			; height is become 3 
	mov	R2, 	14H
	mov	R3, 	15H
	mov	R4, 	16H
	; set next rotate state
	mov	12H, 	#0
	mov	13H, 	#1
	mov	14H, 	#11110011B
	mov	15H, 	#11100111B
ret
h2_b1:
	CJNE	A, 	#1, 	h2_b2
	; reset now state
	mov	R0, 	#3			; height is become 3 
	mov	R2, 	14H
	mov	R3, 	15H
	mov	R4, 	16H
	; set next rotate state
	mov	12H, 	#1			; block sequence number
	mov	13H, 	#1
	mov	14H, 	#11100111B
	mov	15H, 	#11110011B
ret
h2_b2:
	CJNE	A, 	#2, 	h2_b3
ret
h2_b3:
	CJNE	A, 	#3, 	h2_b4
	mov	A, 	13H			; check rotate times
	CJNE	A, 	#0, 	h2_b3_r2
h2_b3_r0:
	; reset now state
	mov	R0, 	#3			; height is become 3 
	mov	R2, 	14H
	mov	R3, 	15H
	mov	R4, 	16H
	; set next rotate state
	mov	12H, 	#3			; block sequence number
	mov	13H, 	#1
	mov	14H, 	#11100011B
	mov	15H, 	#11101111B
ret	
h2_b3_r2:
	; reset now state
	mov	R0, 	#3			; height is become 3 
	mov	R2, 	14H
	mov	R3, 	15H
	mov	R4, 	16H
	; set next rotate state
	mov	12H, 	#3			; block sequence number
	mov	13H, 	#3
	mov	14H, 	#11111011B
	mov	15H, 	#11100011B
ret
h2_b4:
	CJNE	A, 	#4, 	h2_b5
	mov	A, 	13H			; check rotate times
	CJNE	A, 	#0, 	h2_b4_r2
h2_b4_r0:
	; reset now state
	mov	R0, 	#3			; height is become 3 
	mov	R2, 	14H
	mov	R3, 	15H
	mov	R4, 	16H
	; set next rotate state
	mov	12H, 	#3			; block sequence number
	mov	13H, 	#1
	mov	14H, 	#11100011B
	mov	15H, 	#11111011B
ret
h2_b4_r2:
	; reset now state
	mov	R0, 	#3			; height is become 3 
	mov	R2, 	14H
	mov	R3, 	15H
	mov	R4, 	16H
	; set next rotate state
	mov	12H, 	#3			; block sequence number
	mov	13H, 	#3
	mov	14H, 	#11101111B
	mov	15H, 	#11100011B
ret
h2_b5:
	mov	A, 	13H			; check rotate times
	CJNE	A, 	#0, 	h2_b5_r2
h2_b5_r0:
	; reset now state
	mov	R0, 	#3			; height is become 3 
	mov	R2, 	14H
	mov	R3, 	15H
	mov	R4, 	16H
	; set next rotate state
	mov	12H, 	#5			; block sequence number
	mov	13H, 	#1
	mov	14H, 	#11100011B
	mov	15H, 	#11110111B
ret
h2_b5_r2:
	; reset now state
	mov	R0, 	#3			; height is become 3 
	mov	R2, 	14H
	mov	R3, 	15H
	mov	R4, 	16H
	; set next rotate state
	mov	12H, 	#5			; block sequence number
	mov	13H, 	#3
	mov	14H, 	#11110111B
	mov	15H, 	#11100011B
ret
;##########################################################################	
_rotate_height_3:
	; detect margin
	clr	c
	mov	A,	04H
	subb	A,	05H
	CJNE	A,	#4,	_rotate_height_3_margin
	sjmp	_rotate_height_3_error
_rotate_height_3_margin:
	clr	c
	mov	A,	05H
	subb	A,	04H
	CJNE	A,	#3,	_rotate_height_3_touch_detect
	sjmp	_rotate_height_3_error
_rotate_height_3_touch_detect:
	; detect touch
	;row 3
	mov	A, 	R6
	mov	11H, 	R4
	mov	10H,	15H
	lcall	_rotate_touch_detect
	CJNE	A,	1FH,	_rotate_height_3_error
	;row 2
	mov	A, 	R6
	dec	A
	mov	11H, 	R3
	mov	10H,	14H
	lcall	_rotate_touch_detect
	CJNE	A,	1FH,	_rotate_height_3_error
	sjmp	_rotate_height_3_c2
_rotate_height_3_error:
	mov	14h,	52h
	mov	15h,	53h
	ret
_rotate_height_3_c2:
	; start rotate
	;row 3
	mov	A, 	R6
	mov	11H, 	R4
	lcall	_recover_init
	ANL	A, 	15H
	mov	@R1, 	A
	;row 2
	mov	A, 	R6
	dec	A
	mov	11H, 	R3
	lcall	_recover_init
	ANL	A, 	14H
	mov	@R1, 	A
	;row 1
	mov	A, 	R6
	dec	A
	dec	A
	mov	11H, 	R2
	lcall 	_recover_init
	mov	@R1, 	A
	; jump to block number
	mov	A, 	12H
	CJNE	A, 	#0, 	h3_b1
h3_b0:
	; reset now state
	mov	R0, 	#2			; height is become 3 
	mov	R2, 	14H
	mov	R3, 	15H
	; set next rotate state
	mov	12H, 	#0
	mov	13H, 	#0
	mov	14H, 	#11101111B
	mov	15H, 	#11100111B
	mov	16H, 	#11110111B
ret
h3_b1:
	CJNE	A, 	#1, 	h3_b2
	; reset now state
	mov	R0, 	#2			; height is become 3 
	mov	R2, 	14H
	mov	R3, 	15H
	; set next rotate state
	mov	12H, 	#1			; block sequence number
	mov	13H, 	#0
	mov	14H, 	#11110111B
	mov	15H, 	#11100111B
	mov	16H, 	#11101111B
ret
h3_b2:
	CJNE	A, 	#2, 	h3_b3
ret
h3_b3:
	CJNE	A, 	#3, 	h3_b4
	mov	A, 	13H			; check rotate times
	CJNE	A, 	#1, 	h3_b3_r3
h3_b3_r1:
	; reset now state
	mov	R0, 	#2			; height is become 3 
	mov	R2, 	14H
	mov	R3, 	15H
	; set next rotate state
	mov	12H, 	#3			; block sequence number
	mov	13H, 	#2
	mov	14H, 	#11100111B
	mov	15H, 	#11110111B
	mov	16H, 	#11110111B
ret	
h3_b3_r3:
	; reset now state
	mov	R0, 	#2			; height is become 3 
	mov	R2, 	14H
	mov	R3, 	15H
	; set next rotate state
	mov	12H, 	#3			; block sequence number
	mov	13H, 	#0
	mov	14H, 	#11110111B
	mov	15H, 	#11110111B
	mov	16H, 	#11110011B
ret
h3_b4:
	CJNE	A, 	#4, 	h3_b5
	mov	A, 	13H			; check rotate times
	CJNE	A, 	#1, 	h3_b4_r3
h3_b4_r1:
	; reset now state
	mov	R0, 	#2			; height is become 3 
	mov	R2, 	14H
	mov	R3, 	15H
	; set next rotate state
	mov	12H, 	#3			; block sequence number
	mov	13H, 	#2
	mov	14H, 	#11110011B
	mov	15H, 	#11110111B
	mov	16H, 	#11110111B
ret
h3_b4_r3:
	; reset now state
	mov	R0, 	#2			; height is become 3 
	mov	R2, 	14H
	mov	R3, 	15H
	; set next rotate state
	mov	12H, 	#3			; block sequence number
	mov	13H, 	#0
	mov	14H, 	#11110111B
	mov	15H, 	#11110111B
	mov	16H, 	#11100111B
ret	
h3_b5:
	mov	A, 	13H			; check rotate times
	CJNE	A, 	#1, 	h3_b5_r3
h3_b5_r1:
	; reset now state
	mov	R0, 	#2			; height is become 3 
	mov	R2, 	14H
	mov	R3, 	15H
	; set next rotate state
	mov	12H, 	#5			; block sequence number
	mov	13H, 	#2
	mov	14H, 	#11110111B
	mov	15H, 	#11100111B
	mov	16H, 	#11110111B
ret
h3_b5_r3:
	; reset now state
	mov	R0, 	#2			; height is become 3 
	mov	R2, 	14H
	mov	R3, 	15H
	; set next rotate state
	mov	12H, 	#5			; block sequence number
	mov	13H, 	#0
	mov	14H, 	#11110111B
	mov	15H, 	#11110011B
	mov	16H, 	#11110111B
ret	
;##########################################################################
_rotate_height_1or4:
	; detect margin
	mov	A, 	R6
	CJNE	A, 	#30H, 	_rotate_height_1_c
	sjmp	_rotate_height_1_error
_rotate_height_1_c:
	mov	A, 	13H			; check rotate times
	CJNE	A, 	#0, 	h4_b6_r1
h4_b6_r0:
	; detect touch
	;row 4
	mov	A, 	R6
	add	A,	#2
	mov	11H, 	#11111111B
	mov	10H,	17H
	lcall	_rotate_touch_detect
	CJNE	A,	1FH,	_rotate_height_1_error
	;row 3
	mov	A, 	R6
	inc	A
	mov	11H, 	#11111111B
	mov	10H,	16H
	lcall	_rotate_touch_detect
	CJNE	A,	1FH,	_rotate_height_1_error
	;row 2
	mov	A, 	R6
	mov	11H, 	R2
	mov	10H,	15H
	lcall	_rotate_touch_detect
	CJNE	A,	1FH,	_rotate_height_1_error
	;row 1
	mov	A, 	R6
	dec	A
	mov	11H, 	#11111111B
	mov	10H,	14H
	lcall	_rotate_touch_detect
	CJNE	A,	1FH,	_rotate_height_1_error
	sjmp	_rotate_height_1_c2
_rotate_height_1_error:
	mov	14h,	52h
	mov	15h,	53h
	mov	16h,	54h
	mov	17h,	55h
ret
_rotate_height_1_c2:
	; row 4
	INC	1EH
	INC	1EH
	mov	A, 	R6
	mov	R1, 	A
	mov	A, 	@R1
	ANL	A, 	17H
	mov	@R1, 	A
	; row 3
	mov	A, 	R6
	dec	A
	mov	R1, 	A
	mov	A, 	@R1
	ANL	A, 	16H
	mov	@R1, 	A
	; row 2
	mov	A, 	R6
	subb	A, 	#2
	mov	11H, 	R2
	lcall	_recover_init
	ANL	A, 	15H
	mov	@R1, 	A
	; row 1
	mov	A, 	R6
	subb	A, 	#3
	mov	R1,	A
	mov	A, 	@R1
	ANL	A, 	14H
	mov	@R1, 	A
	; reset now state
	mov	R0, 	#4			; height is become 3 
	mov	R2, 	14H
	mov	R3, 	15H
	mov	R4, 	16H
	mov	R5, 	17H
	; set next rotate state
	mov	12H, 	#6			; block sequence number
	mov	13H, 	#1
	mov	14H, 	#11000011B
ret
h4_b6_r1:
	; detect margin
	clr	c
	mov	A,	04H
	subb	A,	05H
	CJNE	A,	#3,	_rotate_height_4_margi1
	sjmp	_rotate_height_4_error
_rotate_height_4_margi1:
	CJNE	A,	#4,	_rotate_height_4_margin2
	sjmp	_rotate_height_4_error
_rotate_height_4_margin2:
	clr	c
	mov	A,	05H
	subb	A,	04H
	CJNE	A,	#2,	_rotate_height_4_margin3
	sjmp	_rotate_height_4_error
_rotate_height_4_margin3:
	CJNE	A,	#3,	_rotate_height_4_touch_detect
	sjmp	_rotate_height_4_error
	
_rotate_height_4_touch_detect:
	; detect touch
	;row 1
	mov	A, 	R6
	subb	A,	#2
	mov	11H, 	R3
	mov	10H,	14H
	lcall	_rotate_touch_detect
	CJNE	A,	1FH,	_rotate_height_4_error
	sjmp	_rotate_height_4_c2
_rotate_height_4_error:
	mov	14h,	52h
	mov	15h,	53h
	mov	16h,	54h
	mov	17h,	55h
	ret
_rotate_height_4_c2:
	;row 4
	mov	A, 	R6
	mov	11H, 	R5
	lcall	_recover_init
	mov	@R1, 	A
	;row 3
	dec	1EH
	mov	A, 	R6
	mov	11H, 	R4
	lcall	_recover_init
	mov	@R1, 	A
	;row 2
	dec	1EH
	mov	A, 	R6
	mov	11H, 	R3
	lcall	_recover_init
	ANL	A, 	14H
	mov	@R1, 	A
	;row 1
	mov	A, 	R6
	dec	A
	mov	11H, 	R2
	lcall	_recover_init
	mov	@R1, 	A
	; reset now state
	mov	R0, 	#1			; height is become 1
	mov	R2, 	14H
	; set next rotate state
	mov	12H, 	#6			; block sequence number
	mov	13H, 	#0
	mov	14H, 	#11110111B
	mov	15H, 	#11110111B
	mov	16H, 	#11110111B
	mov	17H, 	#11110111B
ret
;##########################################################################
_rotate_touch_detect:
	lcall	_recover_init
	mov	1FH,	A
	ANL	A,	10H
	mov	42H,	A
	mov	A,	10H
	CPL	A
	ADD	A,	42H
ret
;##########################################################################
_adjust_swift:
	mov	52h,	14h
	mov	53h,	15h
	mov	54h,	16h
	mov	55h,	17h
	; START
	mov	A, 	04H
	mov	19H, 	A
	cjne	A, 	#0, 	_loop_lf
	sjmp	b_c
_loop_lf:
	mov	A, 	17H
	RL	A
	mov	17H, 	A
	mov	A, 	16H
	RL	A
	mov	16H, 	A
	mov	A, 	15H
	RL	A
	mov	15H, 	A
	mov	A, 	14H
	RL	A
	mov	14H, 	A
	djnz	04H, 	_loop_lf
	mov	04H, 	19H
b_c:
	mov	A, 	05H
	mov	19H, 	A
	cjne	A, 	#0, 	_loop_rt
	ret
_loop_rt:
	mov	A, 	17H
	RR	A
	mov	17H, 	A
	mov	A, 	16H
	RR	A
	mov	16H, 	A
	mov	A, 	15H
	RR	A
	mov	15H, 	A
	mov	A, 	14H
	RR	A
	mov	14H, 	A
	djnz	05H, 	_loop_rt
	mov	05H, 	19H
ret
;##########################################################################
_recover_init:
	mov	R1, 	A
	mov	A, 	@R1
	mov	42H, 	A
	mov	A, 	11H
	CPL	A
	ADD	A, 	42H
ret
;############################################################################
_LED_SCANNER:
	lcall	_SOUND
	mov	R1, #30H
	mov	R2, #00000000B
	_LOOP1:
		MOV 	A, R2
		MOV	C, ACC.0
		MOV	P1.4, C
		MOV	C, ACC.1
		MOV	P1.5, C
		MOV	C, ACC.2
		MOV	P1.6, C
		MOV	C, ACC.3
		MOV	P1.7, C
		MOV 	P0, @R1
		mov	c,	P0.7
		mov	P1.0,	C
		lcall	_TIMER_DELAY
		INC	R1
		INC	R2
	CJNE 	R1, #38H, _LOOP1
	lcall	_SOUND
	_LOOP2:
		mov	A,	R2
		MOV	C, ACC.0
		MOV	P1.4, C
		MOV	C, ACC.1
		MOV	P1.5, C
		MOV	C, ACC.2
		MOV	P1.6, C
		MOV	C, ACC.3
		MOV	P1.7, C
		MOV 	P2, @R1
		INC	R1
		INC	R2
		lcall	_TIMER_DELAY
	CJNE 	R1, #40H, _LOOP2
	lcall	_SOUND
ret
;############################################################################
_TIMER_DELAY:
	mov 56H,60h
_DELAY_J:
	mov 57H,61h
_DELAY_I:
	djnz 57H,_DELAY_I
	djnz 56H,_DELAY_J
	ret
;############################################################################
_PUT_LCD:
	mov	A, #00H		;print STR_1 on LCD
	mov	DPTR, #_STR_TOP
	lcall	PUTS_LCD
	lcall	PUTS_DATA
	
	mov	A, #0AH		;print STR_1 on LCD
	mov	DPTR, #_STR_NEXT
	lcall	PUTS_LCD
	
	MOV	A, 43H
	mov	DPTR,#8001H	;Display on LCD
	movx	@DPTR,A
	
	mov	A, #40H		;print STR_2 on LCD
	mov	DPTR, #_STR_LV
	lcall	PUTS_LCD
	
	mov	A, #45H
	mov	R4, 29H
	CJNE	R4, #0, LEV_2
	mov	DPTR, #_STR_LEV_1
	sjmp	PUT_LEV
LEV_2:
	CJNE	R4, #1, LEV_3
	mov	DPTR, #_STR_LEV_2
	sjmp	PUT_LEV
LEV_3:
	CJNE	R4, #2, LEV_4
	mov	DPTR, #_STR_LEV_3
	sjmp	PUT_LEV
LEV_4:
	mov	DPTR, #_STR_LEV_4
PUT_LEV:
	lcall	PUTS_LCD
ret
;############################################################################
PUTS_DATA:
	MOV	A, #85H
	lcall	WAIT_DISP_READY
	mov	dptr,#8000H
	movx	@dptr,A
	
	MOV	A, 28H
	MOV	B, #100
	DIV 	AB
	ADD	A, #30H
	lcall	WAIT_DISP_READY
	mov	dptr,#8001H	;Display on LCD
	movx	@dptr,A
	
	MOV	A, B
	MOV	B, #10
	DIV 	AB
	ADD	A, #30H
	lcall	WAIT_DISP_READY
	mov	dptr,#8001H	;Display on LCD
	movx	@dptr,A
	
	MOV	A, B
	ADD	A, #30H
	lcall	WAIT_DISP_READY
	mov	dptr,#8001H	;Display on LCD
	movx	@dptr,A
	ret
;############################################################################
PUTS_LCD:
	orl	A,#80H
	mov	27H,#0FFH	;0xFF = -1
	push	DPH	
	push	DPL

        lcall	WAIT_DISP_READY
	mov	dptr,#8000H	;Set the position on screen
	movx	@dptr,A	
	
	pop	DPL		
	pop	DPH
;############################################################################
_PUTS_STRING:			;for(R4 = 0 ; _STR_1[R4]!='\0' ; R4++)
	mov	A,27H
	movc	A, @A+DPTR	;LCM_DR_W = _STR_1[i]
	jz	_PUTS_STRING_END
	push	DPH
	push	DPL
	mov	dptr,#8001H	;Display on LCD
	movx	@dptr,A
	pop	DPL
	pop	DPH
        lcall	WAIT_DISP_READY
	inc	27H
	ajmp	_PUTS_STRING
_PUTS_STRING_END:
	ret
;############################################################################
_STR_LV:
	DB "Lv : "
	DB 00H
_STR_TOP:
	DB "Pt : "
	DB 00H
_STR_LEV_1:
	DB "EASY"
	DB 00H
_STR_LEV_2:
	DB "NORMAL"
	DB 00H
_STR_LEV_3:
	DB "HARD"
	DB 00H
_STR_LEV_4:
	DB "CRAZY"
	DB 00H
_STR_NEXT:
	DB "Next:"
	DB 00H
;############################################################################
_INIT_LCD:
	mov	DPTR,#8000H	;LCD Addres Mapping 0x8000

	mov	A,#38H		;Set 8-bit I/O, display in 2 line
	lcall   WAIT_DISP_READY
	movx	@DPTR,A	

	mov	A,#0EH		;Set display cursor, no flashing
	lcall   WAIT_DISP_READY
	movx	@DPTR,A

	mov	A,#06H		;Set move cursor in each write to the right, no shift
	lcall   WAIT_DISP_READY
	movx	@DPTR,A

	mov	A,#01H		;Clear display
	lcall   WAIT_DISP_READY
	movx	@DPTR,A
	mov	R0, #00111111B
	_Load:
	mov	DPTR, #8000H
	mov	A, #40H
	orl	A, R0
	lcall   WAIT_DISP_READY
	movx	@DPTR, A
	mov 	A, R0
		
	mov	DPTR, #SYMBOL
	movc	A, @A+DPTR
	mov	DPTR, #8001H
	lcall   WAIT_DISP_READY
	movx	@DPTR, A
		
	DEC	R0
	mov	A, R0
	JNB	ACC.7, _Load	
	ret
;############################################################################
WAIT_DISP_READY:                        ; check the busy bit on display
	push dph
	push dpl
	push acc
WAIT_DISP_READY_I:
        mov dptr, #8002h
        movx A, @dptr
        jb Acc.7, WAIT_DISP_READY_I
        pop acc
	pop dpl
	pop dph
        ret
;############################################################################
ED_MELODY:
;;;;;;;;;;;;;;;;
db 12
 db 2
db 7
 db 2
db 4
 db 2
db 9
 db 1
db 12
 db 1
db 9
 db 1
db 8
 db 1
db 10
 db 1
db 8
 db 1
db 4
 db 1
db 2
 db 1
db 4
 db 1
;;;;;;;;;;;;;;;;
db 00
db 00

MELODY:
;;;;;;;;;;;;;;;
db 4
 db 1
db 7
 db 1
db 9
 db 1
db 9
 db 2
db 9
 db 1
db 11
 db 1
db 12
 db 1
db 12
 db 2
db 12
 db 1
db 14
 db 1
db 11
 db 1
db 11
 db 2
db 9
 db 1
db 7
 db 1
db 7
 db 1
db 9
 db 2
db 4
 db 1
db 7
 db 1
db 9
 db 1
db 9
 db 2
db 9
 db 1
db 11
 db 1
db 12
 db 1
db 12
 db 2
db 12
 db 1
db 14
 db 1
db 11
 db 1
db 11
 db 2
db 9
 db 1
db 7
 db 1
db 9
 db 2
db 4
 db 1
db 7
 db 1
db 9
 db 1
db 9
 db 2
db 9
 db 1
db 12
 db 1
db 14
 db 1
db 14
 db 2
db 14
 db 1
db 16
 db 1
db 17
 db 1
db 17
 db 2
db 16
 db 1
db 14
 db 1
db 16
 db 1
db 9
 db 2
db 9
 db 1
db 11
 db 1
db 12
 db 1
db 12
 db 2
db 12
 db 1
db 14
 db 1
db 16
 db 1
db 9
 db 2
db 9
 db 1
db 12
 db 1
db 11
 db 1
db 11
 db 3
db 9
 db 1
db 7
 db 1
db 9
 db 3
;;;;;;;;;;;;;;;;
db 00
db 00

TONES:
db 242  ;261.6	C4 0
 db 60
db 243  ;277.2
 db 2
db 243  ;293.7	D4 4
 db 189
db 244  ;311.1
 db 109
db 245  ;329.6	E4 8
 db 19
db 245  ;349.2	F4 10
 db 176
db 246  ;370.0
 db 68
db 246  ;392.0	G4 14
 db 208
db 247  ;415.3
 db 84
db 247  ;440.0	A4 18
 db 208
db 248  ;466.2
 db 70
db 248  ;493.9	B4 22
 db 181
db 249  ;523.3	C5 24
 db 30
db 249  ;554.4
 db 129
db 249  ;587.3	D5 28
 db 222
db 250  ;622.3
 db 54
db 250  ;659.3	E5 32
 db 137
db 250  ;698.5	F5 34
 db 216
db 251  ;740.0
 db 34
db 251  ;784.0
 db 103
db 251  ;830.6
 db 169
db 251  ;880.0
 db 232
db 252  ;932.3
 db 35
db 252  ;987.8
 db 90
db 252  ;1046.5
 db 142
 
SYMBOL:	

db 00000000b  ;0
db 00000000b
db 00000111b
db 00000100b
db 00000100b
db 00011100b
db 00000000b
db 00000000b

db 00000000b  ;1
db 00000000b
db 00011100b
db 00000100b
db 00000100b
db 00000111b
db 00000000b
db 00000000b

db 00000000b  ;2
db 00000000b
db 00001110b
db 00001110b
db 00001110b
db 00000000b
db 00000000b
db 00000000b

db 00000000b  ;3
db 00000000b
db 00000010b
db 00000010b
db 00011110b
db 00000000b
db 00000000b
db 00000000b

db 00000000b  ;4
db 00000000b
db 00010000b
db 00010000b
db 00011110b
db 00000000b
db 00000000b
db 00000000b

db 00000000b  ;5
db 00000100b
db 00000100b
db 00000100b
db 00011111b
db 00000000b
db 00000000b
db 00000000b

db 00000000b  ;6
db 00000000b
db 00000000b
db 00011111b
db 00000000b
db 00000000b
db 00000000b
db 00000000b
	END

```