'******************************************************************************
'Include "_FuncionesPic16F88.bas" *********************************************
'By COS, 20/12/2014, 10/14, 09/14, 07/14, 06/14, 12/13, PSI v7.34 *************
'Pede que algunas opciones no funcionen con este dispositivo ******************
'******************************************************************************
'******************************************************************************
'INICIALIZACIÓN DE PUNTEROS
'_puntero()
'******************************************************************************
'_puntero(): Devuelve la dirección de memoria del primer elemento de un vector.
'******************************************************************************
'******************************************************************************
'GESTIÓN DE EEPROM INTERNA:
'_wreeprom32, _rdeeprom32
'**********************************************************************
'_wreeprom32: Guarda un dato tipo Long en la Eeprom.
'_rdeeprom32: Lee un dato tipo Long de la EEprom.
'_Write_Single: Guarda un dato tipo Single (Float) en la EEProm.
	'Call _Write_Single(V_single, Direccion EEProm)
'_Read_Single: Lee un dato tipo Single (Float) de la EEProm.
	'V_single = _Read_Single(Direccion EEProm)
'***********************************************************************
'RESISTENCIAS DE PULLUP PUERTO B:
'_Set_PullUp(Modo)
	'Modo:
		'_PullUp_On, Modo a On
		'_PullUp_Off, Modo a Off
'***********************************************************************
'***********************************************************************
'INTERRUPCIONES EXTERIORES POR RB0/INT Y RB7:4
'_IntIf: flag de aviso pulso (flanco) interrup. ext. RB0
'_RbIf: flag de aviso interrup. por cambio en RB7:4
'_Set_Int_Ext(Flanco): flanco de disparo de las int. ext. RB0/INT
	'Flanco:
		'_Int_Ext_L_to_H: Interrupción ext. por flanco bajo a alto
		'_Int_Ext_H_to_L: Interrupción ext. por flanco alto a bajo
'***********************************************************************
'***********************************************************************
'FUNCIONES PARA LA GESTION DE LAS INTERRUPCIONES:
'_enable_interrupts(_global), _disable_interrupts(_global)
'***********************************************************************
'_enable_interrupts(_global): Activa interrup. globales y perifericos
'_enable_interrupts(_int_rda): Activa interrupción Usart Rx
'_enable_interrupts(_int_timer0): Activa interrup. TIMER0
'_enable_interrupts(_int_timer1): Activa interrup. TIMER1
'_enable_interrupts(_int_timer2): Activa interrup. TIMER2
'_enable_interrupts(_int_ext) Interrupción Externa por pulso o flanco en RB0/INT
'_enable_interrupts(_int_rb) Interrupción Externa por cambio de estado en los pin RB7:4
'_diable_interrupts(_global): Desactiva interrup. globales y perifericos
'_disable_interrupts(_int_rda): Desactiva interrupción Usart Rx
'_disable_interrupts(_int_timer0): Desactiva interrup. TIMER0
'_disable_interrupts(_int_timer1): Desactiva interrup. TIMER1
'_disable_interrupts(_int_timer2): Desactiva interrup. TIMER2
'_disable_interrupts(_int_ext) Interrupción Externa por pulso o flanco en RB0/INT
'_disable_interrupts(_int_rb) Interrupción Externa por cambio de estado en los pin RB7:4
'***********************************************************************
'***********************************************************************
'USART:
'_error_usart(), _usartif
'***********************************************************************
'_error_usart(): Desbloquea el módulo usart en modo Rx
'_usartif: equivalente al bit de aviso de datos en bufer
'***********************************************************************
'***********************************************************************
'TIMER0:
'***********************************************************************
'_Set_Timer0(Byte), _Clear_timer0(), _Get_timer0(), _tmr0if
'_SetUp_Timer0().
'***********************************************************************
'_setup_timer0(_mode As Byte, _pdiv As Byte): Configura el Timer0
	'_mode:
		'_tmr0_internal: 'Internal clock (Fosc/4)
		'_tmr0_ext_l_to_h: 'External oscillator
		'_tmr0_ext_h_to_l: 'External oscillator
	'_pdiv: 'Preescaler
		'_tmr0_div2: Divide por 2
		'_tmr0_div4: Divide por 4
		'_tmr0_div8: Divide por 8
		'_tmr0_div16: Divide por 16
		'_tmr0_div32: Divide por 32
		'_tmr0_div64: Divide por 64
		'_tmr0_div128: Divide por 128
		'_tmr0_div256: Divide por 256
'_Set_Timer0(Byte): Recarga el contador del TIMER0
'_Get_Timer0(): Lee el contador del TIMER0
'_Clear_Timer0(): Borra el contador del TIMER0
'_Tmr0If: Etiquea el flag de desborde TIMER0
'***********************************************************************
'***********************************************************************
'TIMER2:
'***********************************************************************
'_set_timer2(Byte), _clear_timer2(), _get_timer2(), _tmr2if
'_setup_timer2(), _timer2()
'***********************************************************************
'_setup_timer2(_prediv As Byte, _periodo As Byte, _posdiv As Byte)
	'_Prediv: 'Preescaler
		'_tmr2_disable: Para el Tmr2
		'_tmr2_div1: Divide por 1
		'_tmr2_div4: Divide por 4
		'_tmr2_div16: Divide por 16
	'_Periodo: Carga el registro del TMR2
	'_posdiv: Postscale, Valores comprendidos entre 0 y 16
'_set_timer2(Byte): Recarga el contador del TIMER2
'_get_timer2(): Lee el contador del TIMER2 (Byte)
'_clear_timer2(): Borra el contador del TIMER2
'_tmr2if: Etiquea el flag de desborde TIMER2
'_timer2(): (_on), (_off), activa o para el timer2
'***********************************************************************
'***********************************************************************
'TIMER1:
'***********************************************************************
'_set_timer1(Word), _clear_timer1(), _get_timer1(), _tmr1if
'_setup_timer1(), _timer1().
'***********************************************************************
'_setup_timer1(_mode As Byte, _pdiv As Byte): Configura el Timer1
	'_mode:
		'_tmr1_osctmr1: 'Oscillator TIMER1, pin T1OSI y T1OSO
		'_tmr1_internal: 'Internal clock (Fosc/4)
		'_tmr1_external: 'External oscillator
		'_tmr1_external_sysnc: 'Synchronize external clock input
	'_pdiv: 'Preescaler
		'_tmr1_div1: Divide por 1
		'_tmr1_div2: Divide por 2
		'_tmr1_div4: Divide por 4
		'_tmr1_div8: Divide por 8
'_set_timer1(word): Recarga el contador del TIMER1
'_get_timer1(): Lee el contador del TIMER1
'_clear_timer1(): Borra el contador del TIMER1
'_tmr1if: Etiquea el flag de desborde TIMER1
'_timer1(): (_on), (_off), activa o para el timer1
'***********************************************************************************
'***********************************************************************************
'GESTIÓN MODULO CCP1:
'_setup_ccp1(), _set_pwm1_duty()
'***********************************************************************************
'Call _Setup_CCP1(modo)
	'Modo:
		'_CCP_OFF modulo CCP apagado
		'_CCP_PWM modulo CCP trabajando como PWM
'Call _Set_Pwm1_Duty(Duty)
	'Duty = duración del pulso alto con respecto al pulso bajo.
'************************************************************************************
'************************************************************************************
'WATCHDOG (WDT):
'Funciones para el control del módulo WDT
'_SeUp_WDT(_mode, _prescaler2)'Configura los prescaler del WDT
'_Set_WDT_On()'Activa el módulo
'_Set_WDT_Off()'Para el módulo
'_Restart_WDT()'Reinicia el contador del WDT
'************************************************************************************
'************************************************************************************
'Gestión EEProm
'************************************************************************************
'No retorna valor
'Guarda un Long en la EEprom
'_vpaso es la variable tipo long a guardar en la EEProm
'_direccion es un Word; posición de memoria a guardar en la EEProm
'Call _wreeprom32(_vpaso, _direccion)
Proc _wreeprom32(_vpaso As Long, _direccion As Word)
	Write _direccion, _vpaso.LB
	_direccion = _direccion + 1
	Write _direccion, _vpaso.HB
	_direccion = _direccion + 1
	Write _direccion, _vpaso.3B
	_direccion = _direccion + 1
	Write _direccion, _vpaso.4B
End Proc                                          
'Retorna valor: Long
'Lee un Long de la EEprom
'_rdeeprom32 = variable tipo long donde se almacena valor leido en EEProm
'_direccion es un Word; posición de memoria a leer en la EEProm
Function _rdeeprom32(_direccion As Word) As Long
	Read _direccion, _rdeeprom32.LB
	_direccion = _direccion + 1
	Read _direccion, _rdeeprom32.HB
	_direccion = _direccion + 1
	Read _direccion, _rdeeprom32.3B
	_direccion = _direccion + 1
	Read _direccion, _rdeeprom32.4B
End Function                                      
'No retorna valor
'Guarda una variable tipo Single en la EEprom
'_vpaso es la variable tipo Single a guardar en la EEProm
'_direccion es un Word; posición de memoria a guardar en la EEProm
'Call _write_single(_vpaso, _direccion)
Proc _write_single(_vpaso As Single, _direccion As Word)
	Write _direccion, _vpaso.LB
	_direccion = _direccion + 1
	Write _direccion, _vpaso.HB
	_direccion = _direccion + 1
	Write _direccion, _vpaso.3B
	_direccion = _direccion + 1
	Write _direccion, _vpaso.4B
End Proc                                          
'Retorna valor: Single
'Lee un Single de la EEprom
'_read_single = variable tipo Single donde se almacena valor leido en EEProm
'_direccion es un Word; posición de memoria a leer en la EEProm
Function _read_single(_direccion As Word) As Single
	Read _direccion, _read_single.LB
	_direccion = _direccion + 1
	Read _direccion, _read_single.HB
	_direccion = _direccion + 1
	Read _direccion, _read_single.3B
	_direccion = _direccion + 1
	Read _direccion, _read_single.4B
End Function                                      
'***********************************************************************************
'***********************************************************************************
'Gestion Usart
'***********************************************************************************
Symbol _usartif = PIR1.RCIF  'Asigna nombre al flag interrupción de la usart
'Gestiona el bloqueo de la Usart en modo Rx
Proc _error_usart()
	Dim _papelera As Byte
	If RCSTA.OERR = True Then  'Entraron más datos de los que se extrajeron (bloqueada)
		RCSTA.CREN = 0  'Disable, continua recepción
		_papelera = RCREG  'Vacía buffer usart
		_papelera = RCREG
		RCSTA.CREN = 1  'Enable, Continuous Receive Enable bit*/
	Endif
End Proc                                          
'***************************************************
'***************************************************
'MODULO CCP1
'***************************************************
Const _on = 1
Const _off = 0
'Const _ccp_off = 0
'Const _ccp_pwm = 1
'Selecciona el modo de trabajo del modulo CCP1
Proc _setup_ccp1(_mode As Byte)
	If _mode = 0 Then  'CCP1 a Off
		CCP1CON.CCP1M0 = 0
		CCP1CON.CCP1M1 = 0
		CCP1CON.CCP1M2 = 0
		CCP1CON.CCP1M3 = 0
	Endif

	If _mode = 1 Then  'CCP1 en modo Pwm
		CCP1CON.CCP1M0 = 0
		CCP1CON.CCP1M1 = 0
		CCP1CON.CCP1M2 = 1
		CCP1CON.CCP1M3 = 1
	Endif
End Proc                                          
'Carga el duty cycle
Proc _set_pwm1_duty(_duty As Word)
	CCP1CON.CCP1Y = _duty.0
	CCP1CON.CCP1X = _duty.1
	CCPR1L = ShiftRight(_duty, 2)
End Proc                                          
'***************************************************
'***************************************************
'TIMER2
'***************************************************
'Etiquetas y constantes
Symbol _tmr2if = PIR1.TMR2IF  'Etiquea el flag de desbordamiento Timer2
'ConFigura el TIMER2
'Prescale Select Bits (T2CON: T2CKPS1, T2CKPS0)
Const _tmr2_disable = 0x00  'Timer2 a Off
Const _tmr2_div1 = 0  'Prescale Select bits
Const _tmr2_div4 = 1  'Prescale Select bits
Const _tmr2_div16 = 2  'Prescale Select bits
'Postscale Select Bits (T2CON: TOUTPS3, TOUTPS2, TOUTPS1, TOUTPS0)
'Postscale de 0 a 16.
'prediv: (prescaler) _tmr2_disable, _tmr2_div1, _tmr2_div4, _tmr2_div16
'Period: Cuando se hace reset (8Bit), TMR2 = PR2.
'_posdiv: (postscaler) valores comprendidos entre 0 1 16.
Proc _setup_timer2(_mode As Byte, _periodo As Byte, _posdiv As Byte)
	T2CON = 0x00  'Timer2 a Off
	T2CON.T2CKPS0 = _mode.0
	T2CON.T2CKPS1 = _mode.1
	PR2 = _periodo  'Desborde TMR2 (TMR2 = PR2)
	T2CON.TOUTPS0 = _posdiv.0  'Asigna postscale
	T2CON.TOUTPS1 = _posdiv.1  'Asigna postscale
	T2CON.TOUTPS2 = _posdiv.2  'Asigna postscale
	T2CON.TOUTPS3 = _posdiv.3  'Asigna postscale
End Proc                                          
'Borra el registro del TMR2
Proc _clear_timer2()
		TMR2 = 0  'Borra el byte
		PIR1.TMR2IF = 0  'Flash dosborde a cero
End Proc                                          
'Recarga el registro del TMR
Proc _set_timer2(_reg As Byte)
		TMR2 = _reg  'Recarga el byte
		PIR1.TMR2IF = 0  'Flash dosborde a cero
End Proc                                          
'Devuelve el registro del Tmr2
Function _get_timer2() As Byte
		_get_timer2 = TMR2  'Carga el byte
		PIR1.TMR2IF = 0  'Flash dosborde a cero
End Function                                      
'Activa o para el contador del timer2
Proc _timer2(_on_off As Bit)
	T2CON.TMR2ON = _on_off
End Proc                                          
'***************************************************
'***************************************************
'TIMER1
'***************************************************
'Etiquetas y constantes
Symbol _tmr1if = PIR1.TMR1IF  'Etiquea el flag de desbordamiento Timer1
'Modo de oscilador
Const _tmr1_disable = %00000000  'Timer1 a off
Const _tmr1_internal = %00000000  'Internal clock (Fosc/4)
Const _tmr1_external = %00000110  'External oscillator
Const _tmr1_external_sysnc = %00000010  'Synchronize external clock input
Const _tmr1_osctmr1 = %00001000  'Oscillator TIMER1, pin T1OSI y T1OSO
'Preescale Select Bits (T1CON: T1CKPS1, T1CKPS0)
Const _tmr1_div1 = 0  'Divide por 1
Const _tmr1_div2 = 1  'Divide por 2
Const _tmr1_div4 = 2  'Divide por 4
Const _tmr1_div8 = 3  'Divide por 8
'ConFigura el TIMER1
Proc _setup_timer1(_mode As Byte, _pdiv As Byte)
	T1CON = _mode  'Asigna el tipo de oscilador
	T1CON.T1CKPS1 = _pdiv.1  'Asigna el divisor
	T1CON.T1CKPS0 = _pdiv.0
End Proc                                          
'Borra el registro del TMR
Proc _clear_timer1()
		TMR1H = 0  'Borra el byte alto
		TMR1L = 0  'Borra el byte bajo
		PIR1.TMR1IF = 0  'Flash dosborde a cero
End Proc                                          
'Recarga el registro del TMR
Proc _set_timer1(_reg As Word)
		TMR1H = _reg.HB  'Recarga el byte alto
		TMR1L = _reg.LB  'Recarga el byte bajo
		PIR1.TMR1IF = 0  'Flash dosborde a cero
End Proc                                          
'Devuelve el registro del TMR
Function _get_timer1() As Word
		_get_timer1.HB = TMR1H  'Carga el byte alto
		_get_timer1.LB = TMR1L  'Carga el byte bajo
End Function                                      
'Activa o para el contador del timer1
Proc _timer1(_on_off As Bit)
	T1CON.TMR1ON = _on_off
End Proc                                          
'***************************************************
'***************************************************
'TIMER0
'***************************************************
'Etiquetas y constantes
Symbol _tmr0if = INTCON.TMR0IF  'Flash dosborde
'Modo de oscilador
Const _tmr0_disable = %00000000  'Timer0 a Off
Const _tmr0_internal = %00000000  'Internal clock (Fosc/4)
Const _tmr0_ext_l_to_h = %00100000  'External oscillator
Const _tmr0_ext_h_to_l = %00110000  'Synchronize external clock input
'RTCC_EXT_L_TO_H or RTCC_EXT_H_TO_L
'Preescale Select Bits (OPTION_REG: PS2, PS1, PS0)
Const _tmr0_div2 = 0  'Divide por 2
Const _tmr0_div4 = 1  'Divide por 4
Const _tmr0_div8 = 2  'Divide por 8
Const _tmr0_div16 = 3  'Divide por 16
Const _tmr0_div32 = 4  'Divide por 32
Const _tmr0_div64 = 5  'Divide por 64
Const _tmr0_div128 = 6  'Divide por 128
Const _tmr0_div256 = 7  'Divide por 256
'ConFigura el TIMER1
Proc _setup_timer0(_mode As Byte, _pdiv As Byte)
	OPTION_REG.T0CS = _mode.5  'Asigna el tipo de oscilador
	OPTION_REG.T0SE = _mode.4  'Asigna la transición para el incremento
	OPTION_REG.PSA = 0  'Prescaler es asignado al TMR0
	OPTION_REG.PS2 = _pdiv.2  'bits de la seleccion del factor de division
	OPTION_REG.PS1 = _pdiv.1  'bits de la seleccion del factor de division
	OPTION_REG.PS0 = _pdiv.0  'bits de la seleccion del factor de division
End Proc                                          
'Borra el registro del TMR
Proc _clear_timer0()
	TMR0 = 0  'Borra el contador del TMR0
	INTCON.TMR0IF = 0  'Flash dosborde a cero
End Proc                                          
'Recarga el registro del TMR
Proc _set_timer0(_reg As Byte)
	TMR0 = _reg  'Asigna valor al contador del TMR0
	INTCON.TMR0IF = 0  'Flash dosborde a cero
End Proc                                          
'Devuelve el registro del TMR
Function _get_timer0() As Byte
	_get_timer0 = TMR0  'Asigna el valor del contador del TMR0
End Function                                      
'***************************************************
'***************************************************
'ITERRUPCIONES:
'***************************************************
Const _global = 1  'Interrupciones globales y perifericos
Const _int_rda = 2  'Interrupción Usart Rx
Const _int_timer0 = 0  'Interrupción TIMER0
Const _int_timer1 = 3  'Interrupción TIMER1
Const _int_timer2 = 4  'Interrupción TIMER2
Const _int_ext = 5  'Interrupción Externa por pulso o flanco en RB0/INT
Const _int_rb = 6  'Interrupción Externa por cambio de estado en los pin RB7:4
'Activa interrupciones seleccionadas
Proc _enable_interrupts(_int As Byte)
	If _int = 1 Then INTCON.PEIE = 1  'Bit habilita interrupciones perifericos
	If _int = 1 Then Enable  'INTCON.GIE habilita las interrupciones globales
	If _int = 2 Then PIE1.RCIE = 1  'Activa la interrup. de la usart en modo rx*/
	If _int = 0 Then INTCON.TMR0IE = 1  'Activa la interrup. TIMER0
	If _int = 3 Then PIE1.TMR1IE = 1  'Activa la interrup. TIMER1
	If _int = 4 Then PIE1.TMR2IE = 1  'Activa la interrup. TIMER2
	If _int = 5 Then INTCON.INTE = 1  'Activa la interrup. EXTERNA RB0/INT
	If _int = 6 Then INTCON.RBIE = 1  'Activa la interrup. por cambio RB7:4
End Proc                                          
'Desactiva las interrupciones seleccionadas
Proc _disable_interrupts(_int As Byte)
	If _int = 1 Then INTCON.PEIE = 0  'Bit de deshabilita interrup. perifericos
	If _int = 1 Then Disable  'INTCON.GIE deshabilita las interrup. globales
	If _int = 2 Then PIE1.RCIE = 0  'Deshabilita interrup. de la usart en modo rx*/
	If _int = 0 Then INTCON.TMR0IE = 0  'Deshabilita la interrup. TIMER0
	If _int = 3 Then PIE1.TMR1IE = 0  'Deshabilita la interrup. TIMER1
	If _int = 4 Then PIE1.TMR2IE = 0  'Deshabilita la interrup. TIMER2
	If _int = 5 Then INTCON.INTE = 0  'Deshabilita la interrup. EXTERNA RB0/INT
	If _int = 6 Then INTCON.RBIE = 0  'Deshabilita la interrup. por cambio RB7:4
End Proc                                          
'******************************************************************************
'******************************************************************************
Symbol _intif = INTCON.INTF  'Asigna  nobre al flag de aviso interrup. ext. RB0
Symbol _rbif = INTCON.RBIF  'Asigna nobre al flag de aviso interrup. RB7:4
Const _int_ext_l_to_h = 1  'Interrupción ext. por flanco bajo a alto
Const _int_ext_h_to_l = 0  'Interrupción ext. por flanco alto a bajo
'Establece el flanco de disparo de las int. ext. RB0/INT
Proc _set_int_ext(_flanco As Bit)
	OPTION_REG.INTEDG = _flanco  '_flanco
End Proc                                          
'******************************************************************************
'******************************************************************************
'Activa o desactiva las resistencias de PullUp del puerto B
Const _pullup_on = 0
Const _pullup_off = 1
Proc _set_pullup(_modo As Bit)
	OPTION_REG.7 = _modo  '_RBPU, Enable/Disable PORTB pullups
End Proc                                          
'******************************************************************************
'******************************************************************************
'WATCHDOG (WDT):
'Funciones para el control del módulo WDT
'_SeUp_WDT(_mode, _prescaler2)'Configura los prescaler del WDT
'_Set_WDT_On()'Activa el módulo
'_Set_WDT_Off()'Para el módulo
'_Restart_WDT()'Reinicia el contador del WDT
'----------------------------------------------------------------------
'_Mode (prescaler):
Const _wdt_div32 = 0  '1,024mSeg (1/31250Hz*32div*1000mSeg)
Const _wdt_div64 = 1  '2,048mSeg
Const _wdt_div128 = 2  '4,096mSeg
Const _wdt_div256 = 3  '8,192mSeg
Const _wdt_div512 = 4  '16,384mSeg
Const _wdt_div1024 = 5  '32,768
Const _wdt_div2048 = 6  '65,536
Const _wdt_div4096 = 7  '131,072
Const _wdt_div8192 = 8  '262.144
Const _wdt_div16394 = 9  '524,608
Const _wdt_div32768 = 10  '1048,576
Const _wdt_div65536 = 11  '2097,152
'_Prescaler2:
Const _wdt_noprescaler2 = 0  '0.032mSeg (no se usa, queda asignado al Tmr0)
Const _wdt_div2_ps2 = 1  '0,064mSeg
Const _wdt_div4_ps2 = 2  '0,128mSeg
Const _wdt_div8_ps2 = 3  '0,256mseg
Const _wdt_div16_ps2 = 4  '0,512mSeg
Const _wdt_div32_ps2 = 5  '1,024mSeg (1/31250Hz*32div*1000mSeg)
Const _wdt_div64_ps2 = 6  '2,048mSeg
Const _wdt_div128_ps2 = 7  '4,096mSeg
'Configura el prescaler del WDT (reloj 31250Hz)
Proc _setup_wdt(_mode As Byte, _prescaler2 As Byte)
	'Prescaler del Wdt
	WDTCON.WDTPS0 = _mode.0  'Prescaler Rate Select bits
	WDTCON.WDTPS1 = _mode.1
	WDTCON.WDTPS2 = _mode.2
	WDTCON.WDTPS3 = _mode.3
	'Prescaler2 compartido con el Tmr0
	If _prescaler2 > 0 Then
		OPTION_REG.PSA = 1  'Asigna prescaler2 al WDT
		OPTION_REG.PS0 = _prescaler2.0  'Configura prescaler
		OPTION_REG.PS1 = _prescaler2.1
		OPTION_REG.PS2 = _prescaler2.2
	Else
		OPTION_REG.PSA = 0  'No prescaler2 WDT (asigna al Tmr0)
	Endif
End Proc                                          
'Activa el WDT (si se activa el fuse de WDT se ignora)
Proc _set_wdt_on()
	WDTCON.SWDTEN = 1
End Proc                                          
'Para el WDT (si se activa el fuse de WDT se ignora)
Proc _set_wdt_off()
	WDTCON.SWDTEN = 0
End Proc                                          
Proc _restart_wdt()
	ASM:        clrwdt  'Reinicializa el WDT
End Proc                                          
'******************************************************************************
'******************************************************************************
'Asignación de direcciones de memoria para trabajar con punteros
'******************************************************************************
'Funcion para asignar _punteros de forma automática.
'By COS, 11/11.
'Basic del Pic Simulator IDE (PSI).
'*************************************************
'Longitud minima de los vectores 2 bytes.
'Hay que indicar la direccion primera y última de lal Ram del Pic.
'Ejecutar al principio.
'*************************************************
'Dim x(10) As Byte  'Declara vector
'Dim p_x As Word  'Declara puntero
'x(0) = 0xaa  'Clave para la localización de la variable en memoria
'x(1) = 0xaa  'Clave para la localización de la variable en memoria
'p_x = _puntero(0xaa)  'Asigna la direccion de la variable y clave de busqueda
'Pic16F628A Ram 0x20 to 0x14f
'Pic16F88 Ram 0x20 to 0x1ef
'Pic16F877A Ram 0x20 to 0x1ef
'-------------------------------------------------
'Devuelve la dirección de un vector.
'Los elementos minimos que puede tener el vector son dos.
Const _p_ram_inicio = 0x020  'Inicio de la memoria ram del Pic16F88
Const _p_ram_fin = 0x1ef  'Fin de la memoria ram del Pic16F88
Function _puntero(_clave 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 = _p_ram_inicio To _p_ram_fin  '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 = _clave And _dt1 = _clave 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 <> _clave Then _dr0_ram = _dr1_ram  'Acelera la busqueda
	Next _dr0_ram
End Function                                      
'*******************************************************************************