'******************************************************************************
'Include "_FuncionesCadenasNumeros.bas"
'Funciones para operar con cadenas y números
'By COS, 11/11, v1.1
'Basic Pic Simulator IDE v6.91 (PSI). (actualizada a v7.40 - 03/2016)
'*****************************EJEMPLO PIC EBASIC*******************************
'Puertos del LCD para simulador************************************************
'Define LCD_BITS = 4  'Bus de datos del lcd a 4bit
'Define LCD_DREG = PORTA  'Bus de datos el puerto A
'Define LCD_DBIT = 0  'Bus datos los 4 bit menos significativos, puerto A
'Define LCD_RSREG = PORTB  'Bit de control RS a puerto B
'Define LCD_RSBIT = 7  'Se usa RB7 como RS
'Define LCD_EREG = PORTB  'Bit de control E del puerto B
'Define LCD_EBIT = 6  'Se usa RB6 como E
'Define LCD_COMMANDUS = 100  '2000  'Espera despues de ejecutar comando lcd, uSeg.
'Define LCD_DATAUS = 50  'Espera despues de enviar un dato al LCD, uSeg.
'Define LCD_INITMS = 5  '50  'Espera despues de inicializar el Display
'******************************************************************************
'Define SIMULATION_WAITMS_VALUE = 1  'Ignora los valores de Waitms, solo simulación
'******************************************************************************
'AllDigital  'Pin digitales
'Lcdinit  'Incializa el LCD
'******************************************************************************
'Decración directa de cadenas y sus punteros
'Dim word01 As Byte @ 0x12f  'Se declara variable en la dirección establecida
'Dim word02 As Byte @ 0x13a  'Se declara variable en la dirección establecida
'Dim word03 As Byte @ 0x145  'Se declara variable en la dirección establecida
'Dim p_word01 As Word  'Variable que apuntará a otra variable
'Dim p_word02 As Word  'Variable que apuntará a otra variable
'Dim p_word03 As Word  'Variable que apuntará a otra variable
'p_word01 = 0x12f  'p_word01 apunta a word01
'p_word02 = 0x13a  'p_word02 apunta a word02
'p_word03 = 0x145  'p_word03 apunta a word03
'------------------------------------------------------------------------------
'Call p_word01()  'Inicaliza cadena y puntero
'Call p_word02()  'Inicaliza cadena y puntero
'Call p_word03()  'Inicaliza cadena y puntero
'main:
'Call _strclr(p_word01)  'Inicializa/Borra la variable
'Call _strcdn(p_word01, 0)  'Asigna la cadena 0 a la variable
'Call _strcdn(p_word02, 2)  'Asigna la cadena 1 a la variable
'Call _strcdn(p_word03, 2)  'Asigna la cadena 2 a la variable
'Call _strchr(p_word02, 0)  'Devuelve el caracter indicado en _strchr
'Call _strlen(p_word03)  'Devuelve en _strlen la longitud de la cadena
'Call _strcpy(p_word02, p_word01, 0, 0, False)  'Convierte la primera en la segunda
'Call _strcmp(p_word02, p_word01)  'Compara dos cadenas, _strcmp = 0 (diferentes), = 1 (iguales)
'Lcdout "word01:"  'Imprime en el LCD
'Call _strlen(p_word01)  'Extrae la longitud de la cadena
'Call _strlcd(p_word01, 0, _strlen)  'Imprime en el LCD la cadena
'Lcdcmdout LcdLine2Home  'Cursor al principio de la segunda línea del lcd
'Call _strdcm(p_word01, 0, _strlen)  'Convierte la cadena alfanumeria ca a números
'Lcdout #_strdcm
'Call _strlen(p_word03)
'Lcdout "L1:", #_strlen
'Call _nmrstr(0, p_word03)
'Call _strlen(p_word03)
'Lcdout " L2:", #_strlen
'Lcdcmdout LcdLine2Home
'Lcdout "N:"
'Call _strlcd(p_word03, 0, _strlen)
'Goto main
'End
'**********************************************************************
'Call p_word01()  'Inicaliza cadena y puntero
'Call p_word02()  'Inicaliza cadena y puntero
'Call p_word03()  'Inicaliza cadena y puntero
'**********************************************************************
'Declara cadena y su puntero
Function p_word01() As Word
	Dim word01(15) As Byte  'Declaración de vector
	Const clv = 0xaa  'word01 de busqueda en memoria
	word01(0) = clv
	word01(1) = clv
	p_word01 = _puntero(clv)  'Incializa cadena y declara su puntero
End Function                                      
'Declara cadena y su puntero
Function p_word02() As Word
	Dim word02(15) As Byte  'Declaración de vector
	Const clv = 0xaa  'word01 de busqueda en memoria
	word02(0) = clv
	word02(1) = clv
	p_word02 = _puntero(clv)  'Incializa cadena y declara su puntero
End Function                                      
'Declara cadena y su puntero
Function p_word03() As Word
	Dim word03(15) As Byte  'Declaración de vector
	Const clv = 0xaa  'word01 de busqueda en memoria
	word03(0) = clv
	word03(1) = clv
	p_word03 = _puntero(clv)  'Incializa cadena y declara su puntero
End Function                                      
'**********************************************************************
'Funciones para trabajar con cadenas y numeros
'**********************************************************************
'Asigna la cadena a la variable elegida
Proc _strcdn(direccion As Word, dato As Byte)
	Dim indice As Byte  'Indica el elemento de la lista
	Dim paso As Byte  'Contendrá el elemento de la lista segun el indice
	Dim x As Bit  'Variable auxiliar
	x = 1
	indice = 0
	While x = 1  'Bucle de asignación
		If dato = 0 Then paso = LookUp("123456", 0), indice
		If dato = 1 Then paso = LookUp("Todopic", 0), indice
		If dato = 2 Then paso = LookUp("Basic", 0), indice
		If dato = 3 Then paso = LookUp("**********", 0), indice
		Pointer(direccion) = paso  'Asigna el valor de paso a la dirección que hace referencia variable
		If paso = 0 Then Exit  'Fin del Proc
		indice = indice + 1  'Incrementa indice
		direccion = direccion + 1  'Apunta a la siguiente dirección del vector seleccionado
	Wend
End Proc                                          
'*********************************************************************
'Compone una cadena caracter a caracter especificado, de izquierda a derecha.
'El numero de orden para el primer caracter es el cero.
'Si endstr = 1, marca fin de cadena.
Proc _chrstr(direccion As Word, posicion As Byte, _chr As Byte, endstr As Bit)
	direccion = direccion + posicion  'Calcula la pisición del caracter
	Pointer(direccion) = _chr  'Escribe el caracter
	direccion = direccion + 1  'Apunta a fin de cadena
	If endstr = 1 Then Pointer(direccion) = 0  'Marca fin de cadena
End Proc                                          
'*********************************************************************
'Devuelve el caracter especificado, de izquierda a derecha
'El numero de orden para el primer caracter es el cero
Function _strchr(direccion As Word, valor As Byte) As Byte
	direccion = direccion + valor  'Calcula la posición del caracter
	_strchr = Pointer(direccion)  'Extrae el caracter de la posición
End Function                                      
'*********************************************************************
'Devuelve en _strlen la longitud de la cadena,
'no cuenta el caracter fin de cadena.
Function _strlen(direccion As Word) As Byte
	Dim paso As Byte
	Dim x As Bit
	x = 1
	_strlen = 0
	While x = 1
		paso = Pointer(direccion)  'Lee valor
		If paso = 0 Then Exit  'Sale de la Function
		_strlen = _strlen + 1  'Incrementa longuitud
		direccion = direccion + 1  'Incrementa posición
	Wend
End Function                                      
'*********************************************************************
'Copia la segunda variable en la primera desde incio
'tantos caracteres como indica numero, incio inclusive.
'Si _strcpy = 0 (OK), _strcpy = 1 primera cadena < que la segunda.
'Si error=1 se copian todos los caracteres hasta error.
'Si error=0 se ignora error, cadena 1 tiene que ser >= longitud que la otra.
'Si numero=0, hasta final.
Function _strcpy(direccion As Word, direccion1 As Word, ini As Byte, num As Byte, error As Bit) As Byte
	Dim paso As Byte
	Dim paso1 As Byte
	Dim x As Bit
	_strcpy = 0
	x = 1
	direccion1 = direccion1 + ini  'Dirección del primer elemento de la variable
	While x = 1
		paso = Pointer(direccion)  'paso = valor del contenido de la direccion
		paso1 = Pointer(direccion1)  'pas1 = valor del contenido de la direccion
		If paso = 0 And paso1 > 0 Then _strcpy = 1  'Marca cadena uno < segunda
		If error = True And paso = 0 Then Exit  'Fin cadena uno, fin rutina
		Pointer(direccion) = paso1  'Se asigna al byte de la direccion = paso1
		If paso1 = 0 Then Exit  'Fin cadena segunda, fin rutina
		direccion = direccion + 1  'Siguiente posición cadena uno
		direccion1 = direccion1 + 1  'siguiente posición cadena dos
		If num > 0 Then  'Si numero=0, copia la cadena completa
			If num > 0 Then num = num - 1  'Decrementa caracteres pendientes
			If num = 0 Then  'Se terminaron los caracteres a copiar
				Pointer(direccion) = 0  'Se marca el nuevo fin de cadena
				Exit  'Se sale de la función
			Endif
		Endif
	Wend
End Function                                      
'*********************************************************************
'Compara las dos cadenas, devuelve _strcmp=1 si no son iguales,
'devuelve _strcmp=0 si son iguales.
Function _strcmp(direccion As Word, direccion1 As Word) As Byte
	Dim paso As Byte
	Dim paso1 As Byte
	Dim x As Bit
	x = 1
	While x = 1
		paso = Pointer(direccion)  'Asigna el valor de la pisición Ram
		paso1 = Pointer(direccion1)  'Asigna el valor de la pisición Ram
		If paso = paso1 Then _strcmp = 0  'Ok, caracteres iguales
		If paso <> paso1 Then _strcmp = 1  'Error, cadenas diferentes
		If paso = 0 Or paso1 = 0 Or paso <> paso1 Then Exit  'Termina la función
		direccion = direccion + 1
		direccion1 = direccion1 + 1
	Wend
End Function                                      
'*********************************************************************
'Borra o inicializa la variable
Proc _strclr(direccion As Word)
	Pointer(direccion) = 0  'Asigna a la primera posición fin de cadena
End Proc                                          
'*********************************************************************
'Envia la cadena al LCD, apartir de inicio y
'tantos caracteres como marque numero.
'numero=0=numero=1.
Proc _strlcd(direccion As Word, inicio As Byte, numero As Byte)
	Dim paso As Byte
	Dim x As Bit
	x = 1
	direccion = direccion + inicio  'Dirección del primer elemento de la variable
	While x = 1
		paso = Pointer(direccion)  'Lee valor
		If paso = 0 Then Exit  'Sale de la Function
		Lcdout paso  'Escribe el byte en el lcd
		If numero > 0 Then numero = numero - 1  'Decrementa caracteres pendientes
		If numero = 0 Then Exit  'Sale de la Función
		direccion = direccion + 1  'Incrementa posición del vector
	Wend
End Proc                                          
'*********************************************************************
'Convierte una cadena numérica a su equivalente matemático
'Número máximo de caracteres a convertir 10, equivalente a variable tipo Long.
'direccion= selecciona el elemento de la cadena
'inicio= primer elemento desde donde se comienza la conversión.
'len= numero de caracteres de la cadena a convertir, inicio incluido.
Function _strdcm(direccion As Word, inicio As Byte, _len As Byte) As Long
	Dim paso As Byte
	Dim nn As Byte
	Dim x As Byte
	Dim numero As Long
	_strdcm = 0
	numero = 0
	x = 1
	If _len > 0 Then _len = _len - 1  'Teniendo en cuenta el cero
	direccion = direccion + inicio  'Dirección del primer caracter
	While x = 1
		paso = Pointer(direccion)  'Asigna valor
		If paso = 0 Then Exit  'Sale de la función por fin de cadena
		paso = paso - 48  'Pasa de texto (código ASCII) a valor número
		numero = paso  'Pasa de Byte a Long
		'/*Asigna posición de la cifra
		For nn = 1 To _len
			numero = numero * 10
		Next nn
		'*/
		_strdcm = _strdcm + numero  'Asigna el valor a la posición de la cifra
		If _len = 0 Then Exit  'No hay más digitos
		If _len > 0 Then _len = _len - 1  'Cifra siguiente, hasta terminar
		direccion = direccion + 1  'Selecciona siguiente caracter de la cadena
	Wend
End Function                                      
'**************************************************************
'Convierte un número tipo Long a cadena alfanumerica
'numero = al número a convertir
'direccion = dirección de memoria de la cadena resultante
'_nmrstr = 0 (OK), = 1 se sobrepasó el caracter de fin de cadena
Function _nmrstr(numero As Long, direccion As Word) As Byte
	Dim paso As Byte
	Dim _len As Byte
	Dim flag As Bit
	Dim nn As Byte
	Dim x As Byte
	Dim numero1 As Long
	_nmrstr = 0  'Se borra error
	_len = 9  'Número máximo de digitos a convertir -1
	flag = 0  'Si =0 indica que son ceros a la izquierda, no se procesan
	If numero = 0 Then  'Marca que se procese el cero a la izquierda y Exit
		flag = 1  'Se procesa el cero a la izquierda
		_len = 0  'Fin de la transformación, Exit
	Endif
	x = 1
	While x = 1  'Bucle de control
		numero1 = numero  'Se hace una imagen del número a transformar
		paso = Pointer(direccion)  'Se lee el primer elemento de la cadena
		If paso = 0 Then _nmrstr = 1  'Marca error, cadena corta
		For nn = _len To 1 Step -1  'Selecciona el digito a extraer
			numero1 = numero1 / 10
		Next nn
		paso = numero1 Mod 10  'Extra el digito
		If paso > 0 Then flag = 1  'Marca procesar ceros
		paso = paso + 48  'Pasa valor numérico a cadena, Acsii 48 = "0".
		Pointer(direccion) = paso  'Se asigna elemento a la cadena
		If flag = 1 Then direccion = direccion + 1  'Selecciona siguiente caracter de la cadena
		If _len = 0 Then  'No hay más digitos
			Pointer(direccion) = 0  'Se asigna el cararcter fin de cadena a la cadena
			Exit  'Fuerza la salida de la función
		Endif
		_len = _len - 1  'Cifra siguiente, hasta terminar
	Wend
End Function                                      
'*********************************************************************
'Extrae el digito indicado, hasta 4 digitos (_nmrdig=Word)
'Extrae el digito indicado, hasta 10 digitos (_nmrdig=Long)
'numero = Cifra a descomponer
'digito = Digito a extraer de 0 a 3 (_nmrdig=Word)
'digito = Digito a extraer de 0 a 9 (_nmrdig=Long)
'Los digitos se nombras de derecha a izquierda, cero es el primero
'_nmrdig, retorna el digito.
Function _nmrdig(numero As Word, digito As Byte) As Long
	'Descompone el numero a mostrar en digitos
	Dim nn As Byte
	For nn = 1 To digito
		numero = numero / 10
	Next nn
	_nmrdig = numero Mod 10
End Function                                      
'*********************************************************************
'Numero a mascara tipo digito display 7 segmentos
'numero = numero a procesar
'_nmr7seg, retorna la mascara de los segmentos a activar
Function _nmr7seg(numero As Byte) As Byte
	_nmr7seg = LookUp(0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f), numero
End Function                                      
'*********************************************************************
'Funcion para asignar _punteros de forma automática
'By Dogflu66, 11/11.
'Basic del Pic Simulator IDE (PSI).
'*************************************************
'Longitud minima 2 bytes
'Ejecutar al principio
'*************************************************
'Dim word01(11) As Byte 'Cadena = vector
'Dim word02(11) As Byte 'Cadena = vector
'Dim word03(11) As Byte 'Cadena = vector
'Dim p_word01 As Word  'Variable que apunta a otra variable
'Dim p_word02 As Word  'Variable que apunta a otra variable
'Dim p_word03 As Word  'Variable que apunta a otra variable
'word01(0) = 0xaa
'word01(1) = 0xaa
'p_word01 = _puntero(0xaa)
'word02(0) = 0xaa
'word02(1) = 0xaa
'p_word02 = _puntero(0xaa)
'word03(0) = 0xaa
'word03(1) = 0xaa
'p_word03 = _puntero(0xaa)
'Pic16F628A Ram 0x20 to 0x14f
'Pic16F88 Ram 0x20 to 0x14f
'-------------------------------------------------
'Devuelve la dirección de una variable
Function _puntero(word01 As Byte) As Word
	Dim dr0_ram As Word  'Dirección byte 0
	Dim dr1_ram As Word  'Dirección byte 1
	Dim dt0 As Byte  'Contenido de la dirección byte 0
	Dim dt1 As Byte  'Contenido de la dirección byte 1
	For dr0_ram = 0x020 To 0x14f  'Rutina de busqueda
		dr1_ram = dr0_ram + 1
		dt0 = Pointer(dr0_ram)  'Asignación del contenido de dirección
		dt1 = Pointer(dr1_ram)  'Asignación del contenido de dirección
		If dt0 = word01 And dt1 = word01 Then  'Comparación
			_puntero = dr0_ram  'Asignación de dirección
			Pointer(dr0_ram) = 0  'Inicaliza la variable
			Pointer(dr1_ram) = 0
			Exit  'Sale de la función
		Endif
		If dt1 <> word01 Then dr0_ram = dr1_ram  'Acelera la busqueda
	Next dr0_ram
End Function                                      