;################################################################
;			IMPLEMENTACIONES DE FUNCIONES MODBUS
;################################################################

;----------------------------------------------------------------
;			INCLUIR ESTO EN UN ARCHIVO INC
;----------------------------------------------------------------
;esto es para modbus rtu
lMODBUS
	call	lICRC	;inicio registros CRC

	movlw	HIGH(lMODBUS)
	movwf	PCLATH
	movlw	kEsclavo;direccion del esclavo en el mensaje recibido
	movwf	FSR
	movfw	INDF	;recupero el numero de esclavo del msg recibido
	movwf	rTempReg
	cjne	rTempReg,rDirEsclavo,lFinErrModbus ;no es para mi el msg
	movfw	rTempReg
	call	lIniCRC	;llamo a calcular CRC

	movlw	kFuncion;Direccion de la funcion modbus en RX_Buffer
	movwf	FSR
	movfw	INDF
	movwf	rComando
	call	lIniCRC	;llamo a calcular CRC

	movlw	kArg1A	;Direccion de parte alta de arg1 en RX_Buffer
	movwf	FSR
	movfw	INDF
	movwf	rArg1A	;guardo el argumento en un registro
	call	lIniCRC	;llamo a calcular CRC

	movlw	kArg1B	;Direccion de parte baja de arg en RX_Buffer
	movwf	FSR
	movfw	INDF
	movwf	rArg1B	;guardo el argumento en un registro
	call	lIniCRC	;llamo a calcular CRC

	movlw	kArg2A	;Direccion de parte alta de arg en RX_Buffer
	movwf	FSR
	movfw	INDF
	movwf	rArg2A	;guardo el argumento en un registro
	call	lIniCRC	;llamo a calcular CRC

	movlw	kArg2B	;Direccion de parte baja de arg en RX_Buffer
	movwf	FSR
	movfw	INDF
	movwf	rArg2B	;guardo el argumento en un registro
	call	lIniCRC	;llamo a calcular CRC

	movlw	kCRC_A	;direccion del crc recibido (en buffer RX)
	movwf	FSR
	movfw	INDF
	movwf	rCrcRX_A;guardo en un registro

	movlw	kCRC_B	;direccion del crc recibido (en buffer RX)
	movwf	FSR
	movfw	INDF
	movwf	rCrcRX_B;guardo en un registro

;Verifico que el cheksum recibido sea correcto
	cse		rCrcRX_B,rCRC_B	;comparo partes bajas del crc si son = comparo altas
	goto	lFinErrModbus	;no respondo nada
	cse		rCrcRX_A,rCRC_A	;comparo partes altas del crc si son = sigo si no error
	goto	lFinErrModbus	;no respondo nada

;calculo cheksum comun a todos los comandos
	call	lICRC				;inicializo para calculo CRC
	movlw	TX_Buffer			;apunto a inicio del buffer de tx
	movwf	FSR
	movfw	rDirEsclavo			;cargo numero de esclavo
	movwf	INDF				;escribo en buffer tx
	call	lIniCRC				;envio para calculo del crc

	cjal	rComando,.6,lNoFuncion	;si es mayor que 6 directamente error
;esto es solamente para este equipo
	movfw	rArg2B
	addwf	rArg1B,w
	movwf	rTempReg
	cjal	rTempReg,.106,lNoAddres
	cjbl	rTempReg,.100,lNoAddres
	movlw	.99
	subwf	rArg1B,f

	movfw	rComando
	addwf	PCL
	nop
	goto 	lNoFuncion	;funcion 01
	goto 	lNoFuncion	;funcion 02
	Goto	l03			;funcion 03
	goto 	l04			;funcion 04
	goto	lNoFuncion	;Funcion 05
	goto	l06			;lNoFuncion	;funcion 06
	goto	lFinModbus

;-------------------------------------
;funcion 0x01 no implementada retornar error
;-------------------------------------	
l01	
	goto 	lFinModbus

;-------------------------------------
;funcion 0x02 no implementada retornar error
;-------------------------------------	
l02	
	goto 	lFinModbus

;-------------------------------------
;funcion 0x03 leer registro de la RAM
;-------------------------------------	
l03	bcf		bError			;limpio para indicar que no hay error
;hacer aca los controles para saber si lo que pide esta bien
	incf	FSR
	movfw	rComando		;cargo para devolver comando
	movwf	INDF
	CALL	lIniCRC
	bcf		CARRY
	RLF		rArg1B,f		;direccion de inicio x2 ya que son 16 bits
	movlw	kIniRAM
	addwf	rArg1B			;direccion de inicio de lectura de ram
	bcf		CARRY
	rlf		rArg2B,f		;cantidad de reg a leer x2 ya que son 16 bits
	movlw	kByteCount		;dir de byte count en buffer tx
	movwf	FSR				;CARGO PUNTERO
	movfw	rArg2B			;byteCount
	movwf	INDF			;guardo dato en buffer tx
	call	lIniCRC			;calculo checksum del bytecount
	movlw	.7
	addwf	rArg2B,w
	movwf	rByteCount		;cuantos datos transmitir
	movl	rTempPoint,k1Dato	;cargo puntero de buffer de TX
lLeerMas
	mov		FSR,rArg1B		;cargo puntero lectura
	moVfw	INDF			;leo
	movwf	rTempReg		;guardo en temporal
	mov		FSR,rTempPoint	;cargo puntero buffer TX
	movfw	rTempReg		;cargo dato a guardar en buffer de TX
	movwf	INDF			;guardo en buffer
	call	lIniCRC			;calculo checksum
	incf	rArg1B			;incremento puntero lectura
	incf	rTempPoint		;incremento puntero escritura
	decfsz	rArg2B			;lei todo...?
	goto	lLeerMas		;no -> sigo leyendo	
	incf	FSR
	goto	lFinModbus		;si -> me voy


;-------------------------------------
;funcion 0x04 leer registro de la EEPROM
;-------------------------------------	
l04	bcf		bError				;limpio para indicar que no hay error
	incf	FSR
	movfw	rComando			;cargo para devolver comando
	movwf	INDF
	CALL	lIniCRC				;llamo a calcular CRC
	mov		rDirEEPROM,rArg1B	;en este caso es al dir de inicio de lectura	
	BCF		CARRY
	rlf		rDirEEPROM,f
	BCF		CARRY
	rlf		rArg2B,W			;en este caso es la cantidad de registros a leer
	movwf	rArg2B
	CALL	lIniCRC				;llamo a calculo de CRC con Bytecount
	incf	FSR
	movfw	rArg2B
	movwf	INDF				;guardo bytecount	
	addlw	.7
	movwf	rByteCount
	movlw	k1Dato
	movwf	FSR					;Direccion para empezar a guardar en el TX_Buffer

lLeer
	movfw	rDirEEPROM
	call	lLeerEEPROM
	movwf	INDF				;escribo en el buffer
	call	lIniCRC				;calculo cheksum del byte leido
	incf	FSR					;incremento puntero
	incf	rDirEEPROM			;incremento dir eeprom
	decfsz	rArg2B				;decremento para saber si envie todo
	goto	lLeer				;no envie todo, leo otro byte
	goto	lFinModbus	

;-------------------------------------
;funcion 0x05 Forzar una bobina
;-------------------------------------
l05	bcf		bError		;limpio para indicar que no hay error
	csnel	rArg2A,.0	;;que hago con la bobina FF= prendo. 00= apago.
	goto	lOff
	csel	rArg2A,.255
	goto	lFin05
	goto	lOn

lOff
;	bcf		fCondOK;	bcf		pEv
	GOTO	lFin05
lOn	
;	bsf		fCondOK;	bsf		pEv
lFin05
	movlw	.2
	movwf	rByteCount
	goto	lFinModbus

;-------------------------------------
;funcion 0x06 escribir 1(un) registro de la RAM
;-------------------------------------	
l06	bcf		bError				;limpio para indicar que no hay error
	BCF		CARRY
	rlf		rArg1B,f			;x2 ya que es una word
	mov		FSR,rArg1B			;en este caso es al dir de inicio de escritura	
	movfw	rArg2A
	movwf	INDF
	incf	FSR
	movfw	rArg2B
	movwf	INDF
;	bsf		fActNum		

	goto	lCopiaRX_a_TX

;-------------------------------------
;   Calculo del CRC
;-------------------------------------
;inicializa todos los registros de control de cheksum
lICRC
	movlw	0xff
	movwf	rCRC_B
	movwf	rCRC_A
	return

;Tengo que cargar en W el registro a analizar antes de llamar a la rutina
lIniCRC
	xorwf	rCRC_B,f
	movlw	.8
	movwf	rNroBit
lMas
	bcf		CARRY
	rrf		rCRC_A
	rrf		rCRC_B
	btfss	CARRY
	GOTO	lNoOR
	movlw	0xA0
	xorwf	rCRC_A,f
	movlw	.1
	xorwf	rCRC_B,f
lNoOR
	decfsz	rNroBit
	goto	lMas
	return
;-------------------------------------	


lCopiaRX_a_TX
	clrf	rByteCount
	clrf	rTempTX_RX
mas	movlw	RX_Buffer
	movwf	FSR
	movfw	rByteCount
	addwf	FSR
	movfw	INDF
	movwf	rTempTX_RX
	movlw	TX_Buffer
	movwf	FSR
	movfw	rByteCount
	addwf	FSR
	movfw	rTempTX_RX
	movwf	INDF

	incf	rByteCount
	csel	rByteCount,.8
	goto	mas

lNoFuncion	;retorna error de funcion ilegal codigo 01
	movl	rErrModbus,.1
	goto	lError
lNoAddres	;retorna error de direccion erronea codigo 02
	movl	rErrModbus,.2
lError	
	bsf		bError			;seteo para avisar que hay error
	incf	FSR
	movfw	rComando
	movwf	INDF
	CALL	lIniCRC			;llamo a calcular CRC
	incf	FSR
	movlw	.1				;cargo codigo de error
	movwf	INDF
	call	lIniCRC			;llamo a calcular CRC
	movl	rByteCount,.7	;cantidad de datos a responder
	incf	FSR
lFinModbus
	movfw	rCRC_B				;agrego CRC al mensaje
	movwf	INDF
	incf	FSR	
	movfw	rCRC_A
	movwf	INDF
	retlw	.0
lFinErrModbus
	retlw	.1
