;EXAM9.ASM
;String Command
;
MAXBUFFER       EQU    8

;User internal ram area
	ORG     30H

buffer: 	DS      MAXBUFFER
StrBuff:        DS	1		;Restore char form RS232


	ORG	0000H


;*** Power up delay ***
;Wait for other Device
RES:	MOV	R2,#40H
RES1:	MOV	R3,#0
RES2:	DJNZ	R3,RES2
	DJNZ	R2,RES1

	MOV	P1,#0FFH	;OFF All P1 bit

MAIN:	LCALL	InitUART	;Initial UART 9600,n,8,1 no parity

	MOV	DPTR,#Hello
	LCALL	SendSROM
	MOV	DPTR,#Ready0	;Show Prompt
	LCALL	SendSROM

;get
ScanStr:
	MOV	R0,#buffer	;point to buffer
	LCALL	GetStr

	MOV	R0,#buffer	;load buffer Ptr
	LCALL	GetCmd		;found = 1...n
	JZ	ScanEx		; 0 = isn't Command

	MOV	StrBuff,A	;store result in StrBuff

;Check Command No.
;Check Command 1
	XRL	A,#01		;?Compare A=1
	JZ	Cmd1		;switch to x

;Check Command 2
	MOV	A,StrBuff	;Restore
	XRL	A,#02		;?Compare A=2
	JZ	Cmd2
	
	JMP	ScanStr

;Treat Command
Cmd1:	MOV	R0,#buffer+3
	LCALL	LineFeed
	LCALL	SendSRAM	;Show agument
	LCALL	LineFeed

	MOV	dptr,#Ready0	;Show Prompt
	LCALL	SendSROM
	SJMP	ScanStr

Cmd2:	MOV	DPTR,#DoCmd2
	LCALL	SendSROM

	MOV	dptr,#Ready0	;Show Prompt
	LCALL	SendSROM

	JMP	ScanStr


ScanEx:	MOV	DPTR,#ErrMsg1
	LCALL	SendSROM
	LCALL	LineFeed


	JMP	ScanStr


;END MAIN

;*** Get Command ***
;R0    point to Str buffer
;DPTR  point to command
;R2    save
;R7    result
;return command in	A
;	found		1...n
;	not found	0
;
;REG change = R0,R2,R7
;
GetCmd:	MOV	R7,#01		;count
	MOV	A,R0		;save R0->R2
	MOV	R2,A		;Restore Ptr

	MOV	DPTR,#Command1
	LCALL	StrCmp
	JZ	CmdEQU		;A=0 Equ

;If not Equ next Cmp

	INC	R7		;inc result
	MOV	A,R2		;get ptr
	MOV	R0,A		;Reload	Ptr

	MOV	DPTR,#Command2

	LCALL	StrCmp
	JZ	CmdEQU

;not found
	MOV	R7,#0		;result	is NULL

CmdEQU:	MOV	A,R7		;result	in R7
	RET


;StrCmp(@R0,DPTR);
;R0    point to Str buffer
;DPTR  point to command
;reg change  = R0,DPTR
;result in A  0   = Equ
;             FFh = nEqu
StrCmp:	CLR	A
	MOVC	A,@A+dptr
	JZ	StrEq		;end of	str
	XRL	A,@R0		;Compare A=@R0 ?
	JNZ	StrNEq
	       
	INC	R0		;next char in buffer
	INC	dptr		;next command
	JMP	StrCmp
	       
StrNEq:	MOV	A,#0FFh		;not equal
	RET    
StrEq:	CLR	A		;equal ret 0
	RET    

;*** Get String ***
;IN R0 pointer to String Buffer
;R3 count n of Str
;
GetStr:	MOV	R3,#0
GetSnx:	CLR	A
	LCALL	RBYTE		;READ -> A
	LCALL	SBYTE		;A    -> Send ECho
	MOV	StrBuff,A	;Restore char in StrBuff

;check end of str
	XRL	A,#0Dh		;Carriage Return <CR>
	JZ	ChkStr

	MOV	A,StrBuff	;Restore char in StrBuff
	XRL	A,#0Ah		;line feed  LF
	JZ	ChkStr

	MOV	A,StrBuff	;Restore char in StrBuff
	XRL	A,#20h		;Space Bar
	JZ	Din



	MOV	@R0,StrBuff	;store in buffer
	INC	R0		;next point
	INC	R3		;count str

;Test buffer full
	MOV	A,R3
	XRL	A,#MAXBUFFER	;Compare with MAXBUFFER
	JZ	Sendfull	;>= MAXBUFFER

	SJMP	GetSnx

ChkStr:	MOV	A,R3
	JZ	SendOK
	MOV	@R0,#0		;end of String
	RET

Din:	MOV	R0,#buffer
	LCALL	DumpI
	
	MOV	dptr,#Ready0	;Show Prompt
	LCALL	SendSROM

	MOV	R0,#buffer	;Point to buffer
	SJMP	GetStr


SendOK:	MOV	DPTR,#Ready0	;Show Prompt
	LCALL	SendSROM
	SJMP	GetSnx

Sendfull:
	MOV	DPTR,#ErrMsg2
	LCALL	SendSROM
	MOV	R0,#buffer	;Point to buffer
	SJMP	GetStr

;*** Send String in Program Memory ***
;Input 	DPTR
SendSROM:
	CLR	A
	MOVC	A,@A+DPTR	;load char
	JZ	EndStr		;yes end
	LCALL	SBYTE		;send 1	byte
	INC	DPTR		;point to next char
	SJMP	SendSROM		;load next char

EndStr:	RET


;*** Send String in RAM ***
;Input 	R0
SendSRAM:
	MOV	A,@R0
	XRL	A,#00
	JZ	EndRStr		;yes end
	MOV	A,@R0
	LCALL	SBYTE		;send 1	byte
	INC	R0		;point to next char
	SJMP	SendSRAM	;load next char

EndRStr:
	RET


;*** Initial UART ***
InitUART:
	MOV	SCON,#01010010B	;Set SCON Serial Control Mode 1: 8-bit UART (Timer-Based). 
	MOV	TMOD,#00100000B	;Set Mode 2  8-bit Auto-Reload
	MOV	TH1,#0FDH	;Set Baud Rate 9600
	SETB	TR1		;Enable Timer 1
	RET

; ********** SBYTE SUB **********
;SEND BYTE
;IN  =	A
;REG =	NO
SBYTE:	JNB	TI,SBYTE	;Wait For Sending done
	CLR	TI
	MOV	SBUF,A
	RET

; ********** RBYTE SUB **********
;OUT =	A
;REG =	A
RBYTE:	JNB	RI,RBYTE	;Wait For Receive already
	CLR	RI
	MOV	A,SBUF
	RET

;*** Send line feed ***
LineFeed:
	MOV	A,#0Dh
	LCALL	SBYTE
feed:	MOV	A,#0Ah
	LCALL	SBYTE
	RET

;*** DUMP table	in InternalRAM	8 Byte ***
;R0 Ptr	to table in internal RAM
;
;R0,R6,R7
DumpI:	MOV	A,R0
	MOV	R7,A		;store Ptr in R7

	MOV	R6,#8
Dumpx:	MOV	A,@R0
	LCALL	SBYTEH
	INC	R0

	MOV	A,#' '		;separate with ' '
	LCALL	SBYTE

	DJNZ	R6,Dumpx

	MOV	R6,#8
Dspc:	MOV	A,#' '		;separate with ' '
	LCALL	SBYTE
	DJNZ	R6,Dspc

	MOV	A,R7		;Restore Ptr
	MOV	R0,A
	MOV	R6,#8
DASC:	MOV	A,@R0
	MOV	R7,A
	SUBB	A,#' '
	JC	Dmark
	MOV	A,R7
	LCALL	SBYTE
	JMP	Dloop

Dmark:	MOV	A,#'.'
	LCALL	SBYTE

Dloop:	INC	R0
	DJNZ	R6,DASC

	LCALL	LineFeed
	RET

; ********** SBYTEH SUB **********
; SEND 2 BYTE HEX FROM A
; IN  = A
; REG = A,R2,R3
SBYTEH:	LCALL	HTOA
	MOV	A,R2
	LCALL	SBYTE
	MOV	A,R3
	LCALL	SBYTE

	RET

; ********** HTOA SUB **********
; CONVERT HEX TO ASCII
; IN  = A
; OUT = R2,R3
; REG = A,R2,R3

HTOA:	PUSH	ACC
	SWAP	A
	LCALL	HTOAS
	MOV	R2,A
	POP	ACC
	LCALL	HTOAS
	MOV	R3,A
	RET

HTOAS:	ANL	A,#0FH
	CJNE	A,#0AH,$+3
	JNC	HTOAS1
	ORL	A,#30H
	RET
HTOAS1:	SUBB	A,#9
	ORL	A,#40H
	RET

Hello:		DB	0Dh,"*** String Command ***",0Dh,0Ah,00
ErrMsg1:	DB	0Dh,0Ah,'Invalid Command',00
ErrMsg2:	DB	0Dh,0Ah,'buffer full',0Dh,0Ah,00
Ready0:		DB	0Dh,0Ah,'MCS-51>',00

Command1:	DB	'*wr',00
Command2:	DB	'*name',00

DoCmd2:		DB	0Dh,0Ah,'Micro#01',0Dh,0Ah,00


END
