'*****************************************************************************
'Funciones para trabajar con un buffer serie en Basic PSI *******************
'By COS, 10/2013, Pic Simulator IDE v6.94 ************************************
'Include "_FuncionesUartRingBuffer.bas" **************************************
'*****************************************************************************
'Funciones:
'_Receive(), _Buffer, _SetUpRFB(), _Error_Buffer(), _RingBuffer(0)
'*****************************************************************************
'_SetUpRFB(): Inicializa el Ring Buffer
'_Buffer: Variable global que contiene el número de caracteres del Buffer
'_Receive(): Devuelve un caracter del Buffer
'_Error_Buffer(): Resetea el Buffer en caso de bloqueo del módulo Usart
'_RingBuffer(0): Mantiene el Buffer activo, se llama desde las interrupciones
'*****************************************************************************
'Funcion principal del Ring Buffer *******************************************
Function _ringbuffer(_ctrl As Byte) As Byte
	'Variables y reserba de memoria para el Buffer
	Dim _rxhdbf(80) As Byte  'Numero de elementos del ringbuffer
	Const _lgbf = 79  'Numero de elementos del ringbuffer -1
	Dim _hdindex As Byte  'Indice para los caracteres recibidos desde la usart
	Dim _sfindex As Byte  'Indice para los caracteres extraidos del ringbuffer
	Dim _bf As Byte  'Numero de bytes que contiene el ringbuffer
	Dim _papelera As Byte  'Variable auxiliar, preregistro ringbuffer
	Dim _flag As Byte  'Flag para el control interno del ringbuffer
	_flag = 0  'Control
	'Inicializa la función RingBuffer y el módulo Usart
	If _ctrl = 1 Then  'Inicializa la función ringbuffer
		_flag = 0
		_sfindex = 0
		_hdindex = 0
		_ringbuffer = 0
		_bf = 0
		RCSTA.CREN = 0  'Disable, continua recepción
		Hserget _papelera  'Vacia registros usart
		Hserget _papelera
		Hserget _papelera
		RCSTA.CREN = 1  'Enable, Continuous Receive Enable bit*/
		PIE1.RCIE = 1  'Activa la interrupcion de la usart en modo rx*/
	Endif
	'Extrae los elementos del Buffer
	If _ctrl = 2 Then  'Extrae los elementos del ringbuffer
		If _bf > 0 Then
				_ringbuffer = _rxhdbf(_sfindex)
				_bf = _bf - 1
				_sfindex = _sfindex + 1
				If _sfindex > _lgbf Then _sfindex = 0
		Endif
	Endif
	'Llena el bufer con los datos recibidos atravez del módulo Usart
	If _ctrl = 0 Then  'Introduce los elementos al ringbuffer desde la usart
		If PIR1.RCIF = 1 Then  'Si la interrupción de la Usart está activa
			Hserget _papelera
			If _hdindex = _sfindex And _bf = 0 Then _flag = 1
			If _hdindex <> _sfindex Then _flag = 2
			If _flag > 0 Then
				_rxhdbf(_hdindex) = _papelera
				_hdindex = _hdindex + 1
				If _hdindex > _lgbf Then _hdindex = 0
				_bf = _bf + 1
			Endif
		Endif
	Endif
	Call _buffer(_bf)  'Hace visible el número de elementos que contiene el buffer
End Function                                      
'Numero de elementos que contiene el buffer
Function _buffer(_nbuffer As Byte) As Byte
	_buffer = _nbuffer
End Function                                      
'Extrae un caracter del ringbuffer
Function _receive() As Byte
	Disable
	_receive = _ringbuffer(2)
	Enable
End Function                                      
'Inicaliza el ringbuffer desde el programa
Proc _setuprbf()
	Call _ringbuffer(1)
End Proc                                          
'Comprueba si hay error de recepción en la Usart y la desbloquea, borra el buffer.
'Si se respeta el modo de trabajo del algoritmo del Buffer no deberia ser necesario.
Proc error_buffer()
	If RCSTA.OERR = True Then
		Disable
		Call _ringbuffer(1)
		Enable
	Endif
End Proc                                          
'Mantiene el Ring Buffer activo
'On Interrupt
	'Save System
	'Call _ringbuffer(0)  'Llama a la funcion ringbuffer, desde las interrupciones
'Resume