;----------------------------------------------------------------------
;
; Serial EPROM version 1.0 (Rutinas para Lectura y Escritura en una EPROM Serial)
; Copyright (C) 2004 Fabian Esteban Traczuk <fabian.traczuk@gmail.com>
; Julio 2004
;
; This software comes under the GNU public license agreement. See the COPYING
; file in this distribution.
;
; If you use this code (or parts) of it, then please credit me.
;
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; GNU General Public License for more details.
;
; Av. Mitre 810
;	Chivilcoy
;	Buenos Aires
;	ARGENTINA!
;
; If you use this code (or parts) of it, then please credit me. Don't forget it!!! :)
;
; coded for MCS-51 Family Macro Assembler ASEM-51 V1.3
;
;----------------------------------------------------------------------
START CODE 0100H

	;----------------------------------------------------------------
	; 
	;----------------------------------------------------------------

	;----------------------------------------------------------------
	; Para Acceder a la SEPROM
	;----------------------------------------------------------------
	PIN_CS		equ P3.4	;Chip Select		(p1)
	PIN_SK		equ P3.5	;Clock			(p2)
	PIN_DI		equ P3.3	;Data Input To SEPROM	(p3)
	PIN_DO		equ P3.2	;Data Output To SEPROM	(p4)
	DATA_READ_LOW	equ R2		;Contiene el LOW del dato obtenido
	DATA_READ_HIGH	equ R3		;Contiene el HIGH del dato obtenido

	;----------------------------------------------------------------
	; Transmicion de Datos
	;----------------------------------------------------------------
	baud_const equ 253		;19200 baud w/ 11.0592 MHz

	;Parametrizo los registro para poder mandarlos al stack
	REG0		equ 00h	;R0
	REG1		equ 01h	;R1
	REG2 		equ 02h	;R2
	REG3		equ 03h	;R3
	REG4		equ 04h	;R4
	REG5		equ 05h	;R5
	REG6		equ 06h	;R6
	REG7		equ 07h	;R7

	;Vector de Reset
	ORG	0
	JMP	MAIN

;----------------------------------------------------------------------------
	ORG START
MAIN :
	mov	sp, #03Fh	;set stack position

	CALL START_RS232

	;----------------------------------------------------------------------------
	CALL	SR_WRITE_ENABLE	;Borro toda la SEPROM
	CALL	SR_ERASE_ALL
	CALL	SR_WRITE_DISABLE
	CALL	delay_100000us
	CALL	WRITE_FET	;Escribo mi nombre en la SEPROM

;---------------------------------------------------------------
;Main Loop
;---------------------------------------------------------------
MAIN_LOOP :
	MOV	R7, #03h
	MOV	R0, #00h
	
READ_AGAIN :
	CALL	SE_READ_DATA
	MOV	A, DATA_READ_LOW	;LSB
	CALL	RS232_OUT
;	CALL	GET_ASCII
	MOV	A, DATA_READ_HIGH	;MSB
	CALL	RS232_OUT
;	CALL	GET_ASCII
	INC	R0		;Siguiente Direccion
	DJNZ	R7, READ_AGAIN	
;	MOV	R7, #04h
;	MOV	A, #0C0h
;	CALL	LCD_CMD
;READ_AGAIN2 :
;	CALL	SE_READ_DATA
;	MOV	A, DATA_READ_LOW	;LSB
;	CALL	RS232_OUT
;;	CALL	GET_ASCII
;	MOV	A, DATA_READ_HIGH	;MSB
;	CALL	RS232_OUT
;;	CALL	GET_ASCII
;	INC	R0		;Siguiente Direccion
;	DJNZ	R7, READ_AGAIN2
_LOOP :
	JMP	MAIN_LOOP

;----------------------------------------------------------------------------
; WRITE_FET
;	Escribo mi nombre en la SERIAL
;----------------------------------------------------------------------------
WRITE_FET :
	CALL	SR_WRITE_ENABLE
	CALL	delay_100000us
	MOV	R0, #0FFh	;Address
M_WRITE1 :
	;Primera Linea
	INC	R0		;Address++ (00)
	MOV	A, #'F'
	MOV	R2, A		;LSB data
	MOV	A, #'A'
	MOV	R3, A		;MSB data
	CALL	SE_WRITE_DATA	;Escribo Cada Dos Bytes
	CALL	delay_100000us
	INC	R0		;Address++ (01)
	MOV	A, #'B'
	MOV	R2, A		;LSB data
	MOV	A, #'I'
	MOV	R3, A		;MSB data
	CALL	SE_WRITE_DATA	;Escribo Cada Dos Bytes
	CALL	delay_100000us
	INC	R0		;Address++ (02)
	MOV	A, #'A'
	MOV	R2, A		;LSB data
	MOV	A, #'N'
	MOV	R3, A		;MSB data
	CALL	SE_WRITE_DATA	;Escribo Cada Dos Bytes
	CALL	delay_100000us
	CALL	SR_WRITE_DISABLE
	RET


;----------------------------------------------------------------------------
; SE_READ_DATA
;	r0 is word address to read, data is returned in
;	r2 (lsb) and r3 (msb)
;----------------------------------------------------------------------------
SE_READ_DATA :
	SETB    PIN_CS
	NOP
	
	CLR     PIN_SK
	SETB    PIN_DI      ;the start bit
	SETB    PIN_SK
	CLR     PIN_SK
	NOP
	SETB    PIN_SK      ;another '1'
	CLR     PIN_SK
	CLR     PIN_DI      ;and a '0'
	SETB    PIN_SK
	
	MOV     R4, #6
	MOV     A, R0
	RL      A
	RL      A
READ2:  RLC     A
	CLR     PIN_SK
	MOV     PIN_DI, C   ;and do each address bit
	SETB    PIN_SK
	DJNZ    R4, READ2
	CLR     PIN_DI
	MOV     R4, #8
	CLR     A
READ3:  CLR     PIN_SK
	NOP
	SETB    PIN_SK
	MOV     C, PIN_DO
	RLC     A
	DJNZ    R4, READ3
	MOV     DATA_READ_HIGH, A
	MOV     R4, #8
	CLR     A
READ4:  CLR     PIN_SK
	SETB    PIN_SK
	MOV     C, PIN_DO
	RLC     A
	DJNZ    R4, READ4
	MOV     DATA_READ_LOW, A
	CLR     PIN_CS
	CLR     PIN_DI
	RET	

;----------------------------------------------------------------------------
; SE_WRITE_DATA
;	r0 is word address to write
;	r2 (lsb) and r3 (msb)
;----------------------------------------------------------------------------
SE_WRITE_DATA :
	SETB    PIN_CS
	NOP
	CLR     PIN_SK
	SETB    PIN_DI      ;THE START BIT
	SETB    PIN_SK
	CLR     PIN_SK
	CLR     PIN_DI      ;A '0'
	SETB    PIN_SK
	CLR     PIN_SK
	SETB    PIN_DI      ;A '1'
	SETB    PIN_SK
	MOV     R4, #6
	MOV     A, R0
	RL      A
	RL      A
WRITE2: RLC     A
	CLR     PIN_SK
	MOV     PIN_DI, C   ;AND DO EACH ADDRESS BIT
	SETB    PIN_SK
	DJNZ    R4, WRITE2
	MOV     A, R3
	MOV     R4, #8
WRITE3: CLR     PIN_SK
	RLC     A
	MOV     PIN_DI, C
	SETB    PIN_SK
	DJNZ    R4, WRITE3
	MOV     A, R2
	MOV     R4, #8
WRITE4: CLR     PIN_SK
	RLC     A
	MOV     PIN_DI, C
	SETB    PIN_SK
	DJNZ    R4, WRITE4
	CLR     PIN_DI
	CLR     PIN_CS
	NOP
	SETB    PIN_CS
	NOP
	NOP
WRITE5: MOV     C, PIN_DO
	JNC     WRITE5
	NOP
	CLR     PIN_CS
	RET

;----------------------------------------------------------------------------
; SR_WRITE_ENABLE
;----------------------------------------------------------------------------
SR_WRITE_ENABLE :    
        SETB    PIN_CS
        NOP
        CLR     PIN_SK
        SETB    PIN_DI      ;THE START BIT
        SETB    PIN_SK
        CLR     PIN_SK
        CLR     PIN_DI      ;A '0'
        SETB    PIN_SK
        CLR     PIN_SK
        CLR     PIN_DI      ;A '0'
        SETB    PIN_SK
        CLR     PIN_SK
        SETB    PIN_DI      ;A '1'
        SETB    PIN_SK
        CLR     PIN_SK
        SETB    PIN_DI      ;A '1'
        SETB    PIN_SK
        CLR     PIN_SK
        CLR     PIN_DI      ;A '0'
        SETB    PIN_SK
        CLR     PIN_SK
        CLR     PIN_DI      ;A '0'
        SETB    PIN_SK
        CLR     PIN_SK
        CLR     PIN_DI      ;A '0'
        SETB    PIN_SK
        CLR     PIN_SK
        CLR     PIN_DI      ;A '0'
        SETB    PIN_SK
        CLR     PIN_CS
        RET

;----------------------------------------------------------------------------
; SR_WRITE_DISABLE
;----------------------------------------------------------------------------
SR_WRITE_DISABLE :
        SETB    PIN_CS
        NOP
        CLR     PIN_SK
        SETB    PIN_DI      ;THE START BIT
        SETB    PIN_SK
        CLR     PIN_SK
        CLR     PIN_DI      ;A '0'
        SETB    PIN_SK
        CLR     PIN_SK
        CLR     PIN_DI      ;A '0'
        SETB    PIN_SK
        CLR     PIN_SK
        CLR     PIN_DI      ;A '1'	;Segun DataSheet del 93LC46, debe ser 0
        SETB    PIN_SK
        CLR     PIN_SK
        CLR     PIN_DI      ;A '1'	;Segun DataSheet del 93LC46, debe ser 0
        SETB    PIN_SK
        CLR     PIN_SK
        CLR     PIN_DI      ;A '0'
        SETB    PIN_SK
        CLR     PIN_SK
        CLR     PIN_DI      ;A '0'
        SETB    PIN_SK
        CLR     PIN_SK
        CLR     PIN_DI      ;A '0'
        SETB    PIN_SK
        CLR     PIN_SK
        CLR     PIN_DI      ;A '0'
        SETB    PIN_SK
        CLR     PIN_CS
        RET

;----------------------------------------------------------------------------
; SE_ERASE_DATA
;	r0 is word address to erase
;----------------------------------------------------------------------------
SE_ERASE_DATA :
	SETB    PIN_CS
	NOP
	CLR     PIN_SK
	SETB    PIN_DI      ;THE START BIT
	SETB    PIN_SK
	CLR     PIN_SK
	SETB	PIN_DI      ;A '1'
	SETB    PIN_SK
	CLR     PIN_SK
	SETB    PIN_DI      ;A '1'
	SETB    PIN_SK
	MOV     R4, #6
	MOV     A, R0
	RL      A
	RL      A
ERASE_DIR :
	RLC     A
	CLR     PIN_SK
	MOV     PIN_DI, C   ;AND DO EACH ADDRESS BIT
	SETB    PIN_SK
	DJNZ    R4, ERASE_DIR
;------------MMMMMMMMMMMMM....
	CLR     PIN_CS
	RET

;----------------------------------------------------------------------------
; SR_ERASE_ALL
;----------------------------------------------------------------------------
SR_ERASE_ALL :
        SETB    PIN_CS
        NOP
        CLR     PIN_SK
        SETB    PIN_DI      ;THE START BIT
        SETB    PIN_SK
        CLR     PIN_SK
        CLR     PIN_DI      ;A '0'
        SETB    PIN_SK
        CLR     PIN_SK
        CLR     PIN_DI      ;A '0'
        SETB    PIN_SK
        CLR     PIN_SK
        SETB	PIN_DI      ;A '1'
        SETB    PIN_SK
        CLR     PIN_SK
        CLR     PIN_DI      ;A '0'
        SETB    PIN_SK
        CLR     PIN_SK
        CLR     PIN_DI      ;A '0'
        SETB    PIN_SK
        CLR     PIN_SK
        CLR     PIN_DI      ;A '0'
        SETB    PIN_SK
        CLR     PIN_SK
        CLR     PIN_DI      ;A '0'
        SETB    PIN_SK
        CLR     PIN_SK
        CLR     PIN_DI      ;A '0'
        SETB    PIN_SK
        CLR     PIN_CS
        RET

;----------------------------------------------------------------------------
;COMPARA_BYTES
;	Compara el Byte dado en A con el dado B
;	Devuelve A = 01 Si A>B
;	Devuelve A = 00 Si A<B
;	Devuelve A = FF Si A=B
;----------------------------------------------------------------------------
COMPARA_BYTES :
	CLR	C
	XRL	A, #80h		
	XRL	B, #80h		
	SUBB	A, B		
	JZ	A_IGUAL_B	
	JC	A_MENOR_B	
	MOV	A, #01h		;	A_MAYOR_B
	RET
A_MENOR_B:
	MOV	A, #00h
	RET
A_IGUAL_B:
	MOV	A, #0FFh
	RET

; ---------------------------------------------------------------------------
; GET_DEC
; ---------------------------------------------------------------------------
GET_DEC :
	MOV	DPTR, #DEC_STRING
	MOV	R0, #03h
CONV3 :
	PUSH	ACC
	MOV	A, R0
	MOVC	A, @A + DPTR
	MOV	B, A
	POP	ACC
	DIV	AB
	ADD	A, #30h
	;Se Obtuvo el Valor Decimal
	MOV	A, B
	DJNZ	R0, CONV3
	RET
DEC_STRING : DB 0,1,10,100

; ---------------------------------------------------------------------------
; GET_ASCII
; ---------------------------------------------------------------------------
GET_ASCII :	;HEX_STRING
	PUSH	ACC
	SWAP	A
	ANL	A, #0Fh
	ADD	A, #HEX_STRING-MVCOFF3A
	MOVC	A, @A+PC
MVCOFF3A :
	CALL	RS232_STR_OUT
	POP	ACC
	ANL	A, #0Fh
	ADD	A, #HEX_STRING-MVCOFF3B
	MOVC	A, @A+PC
MVCOFF3B :
	CALL	RS232_STR_OUT
	RET
HEX_STRING : DB "0123456789ABCDEF"


;----------------------------------------------------------------------------
delay_100000us :
	mov	r7, #0c8h
delay_100000us_l0 :
	mov	r6, #0f8h
delay_100000us_l1 :
	djnz	r6, delay_100000us_l1
	nop
	djnz	r7, delay_100000us_l0
	ret

;----------------------------------------------------------------------------
;r5 = seconds
delay :
	PUSH	ACC
delaystart :
	MOV	A, #0Ah
delaying :
	CALL	delay_100000us
	DJNZ	ACC, delaying
	djnz	R5, delaystart
	POP	ACC
	RET

;==========================================================================
;=
;=		RUTINAS PARA EL PUERTO SERIE
;=
;==========================================================================
; ---------------------------------------------------------------------------
;	Inicializa Interface RS232
; ---------------------------------------------------------------------------
START_RS232:
	ORL	PCON,#10000000b	; set double baud rate
	MOV	TMOD,#00100010b
	MOV	SCON,#01010000b	; Set Serial for mode 2(8 Bits) & Enable reception
	ORL	TCON,#01010000b	; Start timer 1 both timer
	MOV	A, #baud_const
	MOV	th1, A
	SETB ti			;ti is normally set in this program
	CLR ri			;ri is normally cleared
	RET

; ---------------------------------------------------------------------------
;	Envia Dato al puerto
; ---------------------------------------------------------------------------
RS232_OUT:
	JNB	ti, RS232_OUT
	CLR	ti
	MOV	sbuf, A
	RET

; ---------------------------------------------------------------------------
;	Obtiene Dato del puerto
; ---------------------------------------------------------------------------
RS232_IN:
	JNB	ri, RS232_IN
	MOV	A, sbuf
	CLR	ri
	RET

; ---------------------------------------------------------------------------
;	Envia cadena al RS232
; ---------------------------------------------------------------------------
RS232_STR_OUT:
	CLR A
	MOVC A, @A + DPTR	;Obtengo el caracter
	JZ OUT_STR
	CALL RS232_OUT
	INC DPTR
	JMP RS232_STR_OUT
OUT_STR:
	RET 

END