'******************************************************************************
'Include "_Pic18F46K22Lib.bas" ************************************************
'Pic18F26K22/46k22, OshonSoft Pic18 Basic Compiler v5.80
'By COS, 2025/04/17, 2025/03, 2024/12, 2024/04
'******************************************************************************

'******************************************************************************
'INITIALIZATION OF POINTERS
'Memory address assignment for working with pointers
'Returns the memory address of the first element of an array.
'******************************************************************************
'_PointerWord() 'Pointer assignment Pic18 (2023)
'_Address() ' Obsolete
'******************************************************************************

'******************************************************************************
'MANAGEMENT OF INTERRUPT CONTROL 2 AND PULLUP RESISTANCES OF PORT B:
'******************************************************************************
'Proc SetUp_InterruptControl_2(_register As Byte)
'Activates or deactivates the PullUp resistances of port B
'Proc _Set_PullUp_PortB(_mode As Bit)
'*******************************************************************************

'*******************************************************************************
'Key Pressing:
'Use the constants with the addresses of the assigned ports
'_portAddress: chosen port.
'_pin: pin of the chosen port (0 to 7, the pin has to be configured as a digital input).
'_ActiveState: state that the key has to have to be validated (0 or 1).
'_Button: returns 0 if no key is pressed and 255 if it is.
'_delay: if the key was validated and remains pressed, generates a delay.
'Function _Button_INT(_portAddress As Word, _pin As Byte, _activeState As Bit, _delay As Byte) As Byte
'*******************************************************************************

'*******************************************************************************
'FUNCTIONS FOR INTERRUPT MANAGEMENT:
'_enable_interrupts(_global), _disable_interrupts(_global)
'*******************************************************************************
'_enable_interrupts(_global): Activates global and peripheral interrupts
'_enable_interrupts(_int_rda): Activates Usart Rx interrupt
'_enable_interrupts(_int_timer0): Activates TIMER0 interrupt
'_enable_interrupts(_int_timer1): Activates TIMER1 interrupt
'_enable_interrupts(_int_timer2): Activates TIMER2 interrupt
'_enable_interrupts(_int_ext) External Interrupt by pulse or edge on RB0/INT
'_enable_interrupts(_int_rb) External Interrupt by state change on pins RB7:4
'_disable_interrupts(_global): Deactivates global and peripheral interrupts
'_disable_interrupts(_int_rda): Deactivates Usart Rx interrupt
'_disable_interrupts(_int_timer0): Deactivates TIMER0 interrupt
'_disable_interrupts(_int_timer1): Deactivates TIMER1 interrupt
'_disable_interrupts(_int_timer2): Deactivates TIMER2 interrupt
'_disable_interrupts(_int_ext) External Interrupt by pulse or edge on RB0/INT
'_disable_interrupts(_int_rb) External Interrupt by state change on pins RB7:4
'*******************************************************************************

'*******************************************************************************
'Uart1 and Uart2:
'_Clear_Error_UART1(), _UART1IF, _ERROR_UART1
'_Clear_Error_UART2(), _UART2IF _ERROR_UART2
'*******************************************************************************
'_Clear_Error_UART1(): unblocks the uart1 module in rx mode
'_Clear_Error_UART2(): unblocks the uart2 module in rx mode
'_UART1if: equivalent to the data in buffer warning bit of uart1
'_UART2if: equivalent to the data in buffer warning bit of uart2
'_error_UART1: equivalent to the uart lock warning bit in Rx mode
'_error_UART2: equivalent to the uart lock warning bit in Rx mode
'*******************************************************************************

'*******************************************************************************
'TIMER0:
'*******************************************************************************
'Use the declared constants for easier configuration.
'*******************************************************************************
'Symbol _TMR0IF = INTCON.TMR0IF  'Flash overflow
'Function to configure the T0CON register
'Proc _SetUp_TMR0(_mode As Byte)
'Clears the TMR register
'Proc _Clear_TMR0_8Bit()
'Proc _Clear_TMR0_16Bit()
'Reloads the TMR register
'Proc _Set_TMR0_8Bit(_reg As Byte)
'Reloads the TMR register
'Proc _Set_TMR0_16Bit(_reg As Word)
'Returns the TMR register
'Function _Get_TMR0_8Bit() As Byte
'Function _Get_TMR0_16Bit() As Word
'Proc _Tmr0(_On_Off_bit As Bit)
'*******************************************************************************

'*******************************************************************************
'TIMERS 2, 4, and 6:
'*******************************************************************************
'Use the declared constants for configuration
'*******************************************************************************
'Symbol _TMR2IF = PIR1.TMR2IF  'Flags the Timer2 match
'Symbol _TMR4IF = PIR5.TMR4IF  'Flags the Timer4 match
'Symbol _TMR6IF = PIR5.TMR6IF  'Flags the Timer6 overflow
'Sets the postscaler, timer state, and prescaler in T2CON
'Example: Call _Setup_TMR2(TMRx_PS_1_1 | TMRx_ON | TMRx_PRS_1_1, period)
'Proc _Setup_TMR2(_register As Byte, _period As Byte)
'Sets the postscaler, timer state, and prescaler in T4CON
'Proc _Setup_TMR4(_register As Byte, _period As Byte)
'Sets the postscaler, timer state, and prescaler in T6CON
'Proc _Setup_TMR6(_register As Byte, _period As Byte)
'Activates or stops the timer2 counter
'Proc _Tmr2(_On_Off As Byte)
'Activates or stops the timer4 counter
'Proc _Tmr4(_On_Off As Byte)
'Proc _Tmr6(_On_Off As Byte)
'*******************************************************************************

'*******************************************************************************
'TIMERS 1, 3, and 5:
'*******************************************************************************
'Use the declared constants as arguments
'*******************************************************************************
' Configures TIMER1
'Proc _Setup_Tmr1(_mode As Byte)
' Configures TIMER3
'Proc _Setup_Tmr3(_mode As Byte)
' Configures TIMER5
'Proc _Setup_Tmr5(_mode As Byte)
' Activates or stops the TIMER1 counter
'Proc _Tmr1(_On_Off_bit As Bit)
' Activates or stops the TIMER3 counter
'Proc _Tmr3(_On_Off_bit As Bit)
' Activates or stops the TIMER5 counter
'Proc _Tmr5(_On_Off_bit As Bit)
' Clears the TIMER1 register
'Proc _Clear_Tmr1()
' Clears the TIMER3 register
'Proc _Clear_Tmr3()
' Clears the TIMER5 register
'Proc _Clear_Tmr5()
' Reloads the TIMER1 register
'Proc _Set_Tmr1(_reg As Word)
' Reloads the TIMER3 register
'Proc _Set_Tmr3(_reg As Word)
' Reloads the TIMER5 register
'Proc _Set_Tmr5(_reg As Word)
' Returns the value of the TIMER1 register
'Function _Get_Tmr1() As Word
' Returns the value of the TIMER3 register
'Function _Get_Tmr3() As Word
' Returns the value of the TIMER5 register
'Function _Get_Tmr5() As Word
'**************************************************************************

'End of functions extract
'**************************************************************************

'**************************************************************************
'**************************************************************************
' ECCP MODULE (1, 2, 3, 4, and 5) - Library for PIC18F26K22
'**************************************************************************
'Labels
'Symbol _CCP1IF = PIR1.CCP1IF
'Symbol _CCP2IF = PIR2.CCP2IF
'Symbol _CCP3IF = PIR4.CCP3IF
'Symbol _CCP4IF = PIR4.CCP4IF
'Symbol _CCP5IF = PIR4.CCP5IF
' ----- ECCP Modes Configuration -----
' Functions to set different modes in the CCP modules.
' Use with ECCP constant values as arguments.
' Configuration of the CCP1 module
'Proc _Setup_CCP1(_mode As Byte)
' Configuration of the CCP2 module
'Proc _Setup_CCP2(_mode As Byte)
' Configuration of the CCP3 module
'Proc _Setup_CCP3(_mode As Byte)
' Configuration of the CCP4 module
'Proc _Setup_CCP4(_mode As Byte)
' Configuration of the CCP5 module
'Proc _Setup_CCP5(_mode As Byte)
' ----- Duty Cycle Adjustment for PWM 1, 2, 3, 4, and 5 -----
' Procedures to configure the duty cycle in the CCP modules in PWM mode.
' Duty cycle adjustment for PWM1
'Proc _set_pwm1_duty(_duty As Word)
' Duty cycle adjustment for PWM2
'Proc _set_pwm2_duty(_duty As Word)
' ...........
'Timer selections for CCPx
'Example: Call _Setup_CCP_1_2_3_Timers(CCP1_TIMER1_TIMER2 | CCP2_TIMER3_TIMER4 | CCP3_TIMER5_TIMER6)
'Proc _Setup_CCP_1_2_3_Timers(_timer As Byte)
'Proc _Setup_CCP_4_5_Timers(_timer As Byte)
' ----- Auto-Shutdown Configuration for ECCP 1, 2, and 3 -----
' Configures auto-shutdown options for the ECCP modules.
' Auto-Shutdown configuration for ECCP1
'Proc _SetUp_ECCP1_Auto_ShutDown(_config As Byte)
' Auto-Shutdown configuration for ECCP2
'Proc _SetUp_ECCP2_Auto_ShutDown(_config As Byte)
' ............
'Example: _SetUp_ECCPx_Auto_ShutDown(_ECCP_AS_COMP1 | _PINS_AC_SHUTDOWN_LOW | _PINS_BD_SHUTDOWN_LOW)
' ----- Steering Configuration for PWM 1, 2, and 3 -----
' Configures synchronization and enabling of Steering in PWM modules.
' Reset and delay configuration for PWM1
'Proc _SetUp_PWM1_Restart_Delay(_register As Byte)
' Steering configuration for PWM2
'Proc _SetUp_PWM2_Steering(_register As Byte)
' ............
'***************************************************
' End of Extract for ECCP Library Header
'***************************************************
'**************************************************************************
'**************************************************************************
'WATCHDOG (WDT):
'Functions for controlling the WDT module
'Configure the mode and divider of the WDT through configuration bits.
'Software control and reset:
'_Set_WDT_On()'Activates the module
'_Set_WDT_Off()'Stops the module
'_Restart_WDT()'Resets the WDT counter
'**************************************************************************
'**************************************************************************
'OSCCON: OSCILLATOR CONTROL REGISTER:
'**************************************************************************
'Configures the type of oscillator and operating frequency (configure fuses too)
'Use predefined constants for configuration.
'Example: 	'Clock internal 64Mhz.
	'Call _Setup_Oscillator(_OSC_16MHz_HF)
	'Call _Set_PLL4(_PLL_ON)
'Proc _Setup_Oscillator(_register As Byte)
'**************************************************************************
'Use predefined constants or direct value
'Call _Setup_Oscillator_Finetune(_Finetune) 'Min: 32, Factory: 0, Max: 31
'**************************************************************************
'**************************************************************************
'Usart Management
'**************************************************************************
Symbol _UART1IF = PIR1.RC1IF  'Names the usart1 interrupt flag
Symbol _UART2IF = PIR3.RC2IF  'Names the usart2 interrupt flag
Symbol _UAR_ERROR = RCSTA1.OERR
Symbol _UART1_ERROR = RCSTA1.OERR
Symbol _UART2_ERROR = RCSTA2.1  'OERR
'Manages the locking of Usart1 in Rx mode
Proc _Clear_Error_UART1()
	Dim _trash As Byte
	If RCSTA1.OERR = True Then  'More data entered than extracted (locked)
		RCSTA1.CREN = 0  'Disable, continues reception
		_trash = RCREG1  'Empties usart buffer
		_trash = RCREG1
		RCSTA1.CREN = 1  'Enable, Continuous Receive Enable bit*/
	Endif
End Proc
'Manages the locking of Usart2 in Rx mode
Proc _Clear_Error_UART2()
	Dim _trash As Byte
	If RCSTA2.1 = 1 Then  'OERR More data entered than extracted (locked)
		RCSTA2.4 = 0  'CREN Disable, continues reception
		_trash = RCREG2  'Empties usart buffer
		_trash = RCREG2
		RCSTA2.4 = 1  'CREN Enable, Continuous Receive Enable bit*/
	Endif
End Proc
'***************************************************
'***************************************************
' ECCP MODULE (1, 2, 3, 4, and 5)
'***************************************************
'Labels and constants
Symbol _CCP1IF = PIR1.CCP1IF
Symbol _CCP2IF = PIR2.CCP2IF
Symbol _CCP3IF = PIR4.CCP3IF
Symbol _CCP4IF = PIR4.CCP4IF
Symbol _CCP5IF = PIR4.CCP5IF
'CCP1CON P1M<1:0> DC1B<1:0> CCP1M<3:0>

'Operating modes for CCP
Const _ECCP_OFF = %0000 'ECCP mode disabled.
'Const _ECCP_RESERVED_1 = 0001 'Reserved mode.
Const _ECCP_COMPARE_TOGGLE = %0010 'Comparison mode, toggles output on match.
'Const _ECCP_RESERVED_3 = 0011 'Reserved mode.
Const _ECCP_CAPTURE_FALLING = %0100 'Capture mode on every falling edge.
Const _ECCP_CAPTURE_RISING = %0101 'Capture mode on every rising edge.
Const _ECCP_CAPTURE_4TH_RISING = %0110 'Capture mode on every 4th rising edge.
Const _ECCP_CAPTURE_16TH_RISING = %0111 'Capture mode on every 16th rising edge.
Const _ECCP_COMPARE_SET = %1000 'Comparison mode, sets output on match.
Const _ECCP_COMPARE_CLEAR = %1001 'Comparison mode, clears output on match.
Const _ECCP_COMPARE_INTERRUPT = %1010 'Comparison mode, generates interrupt on match.
Const _ECCP_COMPARE_SPECIAL_EVENT = %1011 'Comparison mode, Special Event Trigger.
Const _ECCP_PWM = %1100 '11xx PWM mode.
'Enhanced PWM Output Configuration bits (PxM<1:0>)
Const _ECCP_SINGLE_OUTPUT = %00000000' PWM simple mode; PxA modulated; PxB as port pin
Const _ECCP_HALF_BRIDGE = %10000000  ' Half-bridge mode; PxA, PxB modulated with dead band control
Const _ECCP_FULL_BRIDGE_FORWARD = %01000000 'Full bridge forward mode; PxD modulated; PxA active; PxB, PxC inactive
Const _ECCP_FULL_BRIDGE_REVERSE = %11000000 'Full bridge reverse mode; PxB modulated; PxC active; PxA, PxD inactive
' Half-Bridge ECCP Modules
Const _ECCP_PWM_HALF_BRIDGE_AH_BH = %1100    ' PWM mode: PxA active-high; PxB active-high
Const _ECCP_PWM_HALF_BRIDGE_AH_BL = %1101    ' PWM mode: PxA active-high; PxB active-low
Const _ECCP_PWM_HALF_BRIDGE_AL_BH = %1110    ' PWM mode: PxA active-low; PxB active-high
Const _ECCP_PWM_HALF_BRIDGE_AL_BL = %1111    ' PWM mode: PxA active-low; PxB active-low
' Full-Bridge ECCP Modules
Const _ECCP_PWM_FULL_BRIDGE_AH_BH = %1100    ' PWM mode: PxA, PxC active-high; PxB, PxD active-high
Const _ECCP_PWM_FULL_BRIDGE_AH_BL = %1101    ' PWM mode: PxA, PxC active-high; PxB, PxD active-low
Const _ECCP_PWM_FULL_BRIDGE_AL_BH = %1110    ' PWM mode: PxA, PxC active-low; PxB, PxD active-high
Const _ECCP_PWM_FULL_BRIDGE_AL_BL = %1111    ' PWM mode: PxA, PxC active-low; PxB, PxD active-low
'Example: Call _Setup_CCP1(ECCP_PWM) 'PWM mode
'Configures the CCP1 module
Proc _Setup_CCP1(_mode As Byte)
		CCP1CON = _mode
End Proc
'Configures the CCP2 module
Proc _Setup_CCP2(_mode As Byte)
		CCP2CON = _mode
End Proc
'Configures the CCP3 module
Proc _Setup_CCP3(_mode As Byte)
		CCP3CON = _mode
End Proc
'Configures the CCP4 module
Proc _Setup_CCP4(_mode As Byte)
		CCP4CON = _mode
End Proc
'Configures the CCP5 module
Proc _Setup_CCP5(_mode As Byte)
		CCP5CON = _mode
End Proc
'Loads the register for the duty cycle PWM1
Proc _set_pwm1_duty(_duty As Word)
    CCP1CON.DC1B0 = _duty.0
    CCP1CON.DC1B1 = _duty.1
    CCPR1L = ShiftRight(_duty, 2)
End Proc
'Loads the register for the duty cycle PWM2
Proc _set_pwm2_duty(_duty As Word)
    CCP2CON.DC2B0 = _duty.0
    CCP2CON.DC2B1 = _duty.1
    CCPR2L = ShiftRight(_duty, 2)
End Proc'Loads the register for the duty cycle PWM1
Proc _set_pwm3_duty(_duty As Word)
    CCP3CON.DC3B0 = _duty.0
    CCP3CON.DC3B1 = _duty.1
    CCPR3L = ShiftRight(_duty, 2)
End Proc
'Loads the register for the duty cycle PWM1
Proc _set_pwm4_duty(_duty As Word)
    CCP4CON.DC4B0 = _duty.0
    CCP4CON.DC4B1 = _duty.1
    CCPR4L = ShiftRight(_duty, 2)
End Proc
'Loads the register for the duty cycle PWM1
Proc _set_pwm5_duty(_duty As Word)
    CCP5CON.DC5B0 = _duty.0
    CCP5CON.DC5B1 = _duty.1
    CCPR5L = ShiftRight(_duty, 2)
End Proc
'Timer selection for CCP1 (Capture/Compare Timer1, 3 and 5. PWM Timer 2, 4 and 6)
'CCPTMRS0: PWM TIMER SELECTION CONTROL REGISTER 0
'C3TSEL<1:0> â€” C2TSEL<1:0> â€” C1TSEL<1:0>
'Timer selections for CCP1 in CCPTMRS0
Const _CCP1_TIMER1_TIMER2 = %000000
Const _CCP1_TIMER3_TIMER4 = %000001
Const _CCP1_TIMER5_TIMER6 = %000010

'Timer selections for CCP2 in CCPTMRS0
Const _CCP2_TIMER1_TIMER2 = %000000
Const _CCP2_TIMER3_TIMER4 = %000100
Const _CCP2_TIMER5_TIMER6 = %001000

'Timer selections for CCP3 in CCPTMRS0
Const _CCP3_TIMER1_TIMER2 = %000000
Const _CCP3_TIMER3_TIMER4 = %010000
Const _CCP3_TIMER5_TIMER6 = %100000

'Example: Call _Setup_CCP_1_2_3_Timers(CCP1_TIMER1_TIMER2 | CCP2_TIMER3_TIMER4 | CCP3_TIMER5_TIMER6)
Proc _Setup_CCP_1_2_3_Timers(_timer As Byte)
    CCPTMRS0 = _timer'ccp1_timer | ccp2_timer | ccp3_timer
End Proc
'Timer selections for CCP4 in CCPTMRS1
Const _CCP4_TIMER1_TIMER2 = %0000
Const _CCP4_TIMER3_TIMER4 = %0001
Const _CCP4_TIMER5_TIMER6 = %0010

'Timer selections for CCP5 in CCPTMRS1
Const _CCP5_TIMER1_TIMER2 = %0000
Const _CCP5_TIMER3_TIMER4 = %0100
Const _CCP5_TIMER5_TIMER6 = %1000

'Example: Call _Setup_CCP_4_5_Timers(CCP4_TIMER1_TIMER2 | CCP5_TIMER5_TIMER4)
Proc _Setup_CCP_4_5_Timers(_timer As Byte)
    CCPTMRS1 = _timer 'ccp4_timer | ccp5_timer
End Proc
'Auto-Shutdown Source Select bits
Const _ECCP_AS_DISABLED = %00000000               ' Auto-shutdown disabled
Const _ECCP_AS_COMP1 = %00100000                  ' Auto-shutdown activated by comparator C1
Const _ECCP_AS_COMP2 = %01000000                  ' Auto-shutdown activated by comparator C2
Const _ECCP_AS_COMP1_OR_COMP2 = %01100000         ' Auto-shutdown activated by comparator C1 or C2
Const _ECCP_AS_FLT0 = %10000000                   ' Auto-shutdown activated by FLT0 pin
Const _ECCP_AS_FLT0_OR_COMP1 = %10100000          ' Auto-shutdown activated by FLT0 or comparator C1
Const _ECCP_AS_FLT0_OR_COMP2 = %11000000          ' Auto-shutdown activated by FLT0 or comparator C2
Const _ECCP_AS_FLT0_OR_COMP1_OR_COMP2 = %11100000 ' Auto-shutdown activated by FLT0, C1 or C2
' Pins Shutdown State Control bits
Const _PINS_SHUTDOWN_LOW = %00000000               ' Pins in low state during shutdown
Const _PINS_SHUTDOWN_HIGH = %00000001              ' Pins in high state during shutdown
Const _PINS_SHUTDOWN_TRISTATE = %00000010          ' Pins in high impedance (tristate) state during shutdown
'Function to configure Auto-Shutdown of the ECCP
'Example: _SetUp_ECCPx_Auto_ShutDown(_ECCP_AS_COMP1 | _PINS_AC_SHUTDOWN_LOW | _PINS_BD_SHUTDOWN_LOW)
Proc _SetUp_ECCP1_Auto_ShutDown(_config As Byte)
    ECCP1AS = _config
End Proc
Proc _SetUp_ECCP2_Auto_ShutDown(_config As Byte)
    ECCP2AS = _config
End Proc
Proc _SetUp_ECCP3_Auto_ShutDown(_config As Byte)
    ECCP3AS = _config
End Proc
'PWM Restart Enable bit and delay
Const _PWM_RESTART_ENABLE = %10000000   ' 1: Automatically restarts PWM after auto-shutdown
Const _PWM_RESTART_DISABLE = %00000000  ' 0: Manual restart required in software after auto-shutdown
'PWM_Delay_Count (Dead-Band): bits (PxDC<6:0>) (modify according to desired delay 0 to 127)
'Function to configure the PWMxCON register
'Example: _SetUp_PWMx_Restart_Delay(_PWM_RESTART_ENABLE | _PWM_DELAY_COUNT)
Proc _SetUp_PWM1_Restart_Delay(_register As Byte)
    PWM1CON = _register
End Proc
'Function to configure the PWMxCON register
Proc _SetUp_PWM2_Restart_Delay(_register As Byte)
    PWM2CON = _register
End Proc
'Function to configure the PWMxCON register
Proc _SetUp_PWM3_Restart_Delay(_register As Byte)
    PWM3CON = _register
End Proc
'Steering Sync bit
Const _STEERING_SYNC_NEXT_PWM = %00010000  ' 1: Direction update in the next PWM period
Const _STEERING_SYNC_INSTANT = %00000000   ' 0: Immediate direction update
' Steering Enable bits
Const _STEERING_ENABLE_D = %00001000  ' 1: PxD carries the PWM waveform
Const _STEERING_DISABLE_D = %00000000 ' 0: PxD assigned to port pin
Const _STEERING_ENABLE_C = %00000100  ' 1: PxC carries the PWM waveform
Const _STEERING_DISABLE_C = %00000000 ' 0: PxC assigned to port pin
Const _STEERING_ENABLE_B = %00000010  ' 1: PxB carries the PWM waveform
Const _STEERING_DISABLE_B = %00000000 ' 0: PxB assigned to port pin
Const _STEERING_ENABLE_A = %00000001  ' 1: PxA carries the PWM waveform
Const _STEERING_DISABLE_A = %00000000 ' 0: PxA assigned to port pin
'Function to configure the PSTRxCON register
'Example: CALL _Config_PSTR1CON(_steering_sync | _steering_d | _steering_c | _steering_b | _steering_a)
Proc _SetUp_PWM1_Steering(_register As Byte)
    PSTR1CON = _register
End Proc
'Function to configure the PSTRxCON register
Proc _SetUp_PWM2_Steering(_register As Byte)
    PSTR2CON = _register
End Proc
'Function to configure the PSTRxCON register
Proc _SetUp_PWM3_Steering(_register As Byte)
    PSTR3CON = _register
End Proc
'***************************************************
'***************************************************
'TIMERS 2, 4, and 6
'***************************************************
'Labels and constants
Symbol _TMR2IF = PIR1.TMR2IF  'Flags the Timer2 match
Symbol _TMR4IF = PIR5.TMR4IF  'Flags the Timer4 match
Symbol _TMR6IF = PIR5.TMR6IF  'Flags the Timer6 overflow
'Timer2/TIMER4/TIMER6 Output Postscaler Select
'TxCON: TxOUTPS<3:0> TMRxON TxCKPS<1:0>
Const TMRx_PS_1_1 =  %0000000  ' 1:1 Postscaler
Const TMRx_PS_1_2 =  %0001000  ' 1:2 Postscaler
Const TMRx_PS_1_3 =  %0010000  ' 1:3 Postscaler
Const TMRx_PS_1_4 =  %0011000  ' 1:4 Postscaler
Const TMRx_PS_1_5 =  %0100000  ' 1:5 Postscaler
Const TMRx_PS_1_6 =  %0101000  ' 1:6 Postscaler
Const TMRx_PS_1_7 =  %0110000  ' 1:7 Postscaler
Const TMRx_PS_1_8 =  %0111000  ' 1:8 Postscaler
Const TMRx_PS_1_9 =  %1000000  ' 1:9 Postscaler
Const TMRx_PS_1_10 = %1001000  ' 1:10 Postscaler
Const TMRx_PS_1_11 = %1010000  ' 1:11 Postscaler
Const TMRx_PS_1_12 = %1011000  ' 1:12 Postscaler
Const TMRx_PS_1_13 = %1100000  ' 1:13 Postscaler
Const TMRx_PS_1_14 = %1101000  ' 1:14 Postscaler
Const TMRx_PS_1_15 = %1110000  ' 1:15 Postscaler
Const TMRx_PS_1_16 = %1111000  ' 1:16 Postscaler
'TimerX On Bit
Const TMRx_ON = %100  ' TimerX is on
Const TMRx_OFF = %000  ' TimerX is off
'Timer2-type Clock Prescale Select
Const TMRx_PRS_1 = %00  ' Prescaler is 1
Const TMRx_PRS_4 = %01  ' Prescaler is 4
Const TMRx_PRS_16 = %10  ' Prescaler is 16
'Sets the postscaler, timer state, and prescaler in T2CON
'Example: Call _Setup_TMR2(TMRx_PS_1_1 | TMRx_ON | TMRx_PRS_1_1, period)
Proc _Setup_TMR2(_register As Byte, _period As Byte)
    T2CON = _register
    PR2 = _period  'Compares TMR2 with PR2.
End Proc
'Sets the postscaler, timer state, and prescaler in T4CON
Proc _Setup_TMR4(_register As Byte, _period As Byte)
    T4CON = _register
    PR4 = _period  'Compares TMR2 with PR4.
End Proc
'Sets the postscaler, timer state, and prescaler in T6CON
Proc _Setup_TMR6(_register As Byte, _period As Byte)
    T6CON = _register
    PR6 = _period  'Compares TMR2 with PR4.
End Proc
'Activates or stops the timer2 counter
Proc _Tmr2(_On_Off As Byte)
	T2CON.TMR2ON = _On_Off.0
End Proc
'Activates or stops the timer4 counter
Proc _Tmr4(_On_Off As Byte)
	T4CON.TMR4ON = _On_Off.0
End Proc'Activates or stops the timer6 counter
Proc _Tmr6(_On_Off As Byte)
	T6CON.TMR6ON = _On_Off.0
End Proc
'***************************************************
'***************************************************
'TIMER(1, 3, and 5)
'***************************************************
'Clock Source for Timer (TMRxCS<1:0>):
'Const _TMR_CLK_EXT = %11000000 (Not to be used, reserved)
Const _TMR_CLK_PIN_OSC = %10000000 '(External clock or crystal)
Const _TMR_CLK_SYS = %01000000 '(System Clock FOSC)
Const _TMR_CLK_INST = %00000000 '(Instruction Clock FOSC/4)
'Prescaler (TxCKPS<1:0>):
Const _TMR_PRESCALE_1_8 = %00110000 '(Prescaler 1:8)
Const _TMR_PRESCALE_1_4 = %00100000 '(Prescaler 1:4)
Const _TMR_PRESCALE_1_2 = %00010000 '(Prescaler 1:2)
Const _TMR_PRESCALE_1_1 = %00000000 '(Prescaler 1:1)
'Secondary Oscillator (TxSOSCEN):
Const _TMR_SOSC_ENABLED = %00001000 '(Secondary oscillator enabled)
Const _TMR_SOSC_DISABLED = %00000000 '(Secondary oscillator disabled)
'External Clock Synchronization (TxSYNC):
Const _TMR_SYNC_EXT_OFF = %00000100 '(Do not synchronize external clock)
Const _TMR_SYNC_EXT_ON = %00000000 '(Synchronize external clock)
'16-bit Read/Write Mode (TxRD16):
Const _TMR_16BIT_MODE = %00000010 '(16-bit mode)
Const _TMR_8BIT_MODE = %00000000 '(8-bit mode)
'Timer On (TMRxON):
Const _TMR_ON = %00000001 '(Timer on)
Const _TMR_OFF = %00000000 '(Timer off)
'Clears interrupt flag
Const _TMR_INT_FLAG_OFF = 0 '(Timer interrupt Flag off)
'Configures TIMER: 1, 3, 5
Symbol _TMR1IF = PIR1.TMR1IF
'Example: Call _setup_timer1(_TMR1_CLK_INST | _TMR1_PRESCALE_1_1 | _TMR1_16BIT_MODE)
Proc _Setup_Tmr1(_mode As Byte)
	T1CON = _mode  'Assigns the configuration
End Proc
Symbol _TMR3IF = PIR2.TMR3IF
Proc _Setup_Tmr3(_mode As Byte)
	T3CON = _mode  'Assigns the configuration
End Proc
Symbol _TMR5IF = PIR5.TMR5IF
Proc _Setup_Tmr5(_mode As Byte)
	T5CON = _mode  'Assigns the configuration
End Proc
Const _Enable = 1
Const _Disable = 0
'Activates or stops the timer1 counter
Proc _Tmr1(_On_Off_bit As Bit)
	T1CON.TMR1ON = _On_Off_bit
End Proc
'Activates or stops the timer3 counter
Proc _Tmr3(_On_Off_bit As Bit)
	T3CON.TMR3ON = _On_Off_bit
End Proc
'Activates or stops the timer5 counter
Proc _Tmr5(_On_Off_bit As Bit)
	T5CON.TMR5ON = _On_Off_bit
End Proc
'Clears the TMR1 register
Proc _Clear_Tmr1()
		TMR1H = 0  'Clears the high byte
		TMR1L = 0  'Clears the low byte
		PIR1.TMR1IF = 0  'Flash overflow to zero
End Proc
'Clears the TMR3 register
Proc _Clear_Tmr3()
		TMR3H = 0  'Clears the high byte
		TMR3L = 0  'Clears the low byte
		PIR2.TMR3IF = 0  'Flash overflow to zero
End Proc
'Clears the TMR5 register
Proc _Clear_Tmr5()
		TMR5H = 0  'Clears the high byte
		TMR5L = 0  'Clears the low byte
		PIR5.TMR5IF = 0  'Flash overflow to zero
End Proc
'Reloads the TMR 1 register
Proc _Set_Tmr1(_reg As Word)
		TMR1H = _reg.HB  'Reloads the high byte
		TMR1L = _reg.LB  'Reloads the low byte
		PIR1.TMR1IF = 0  'Flash overflow to zero
End Proc
'Reloads the TMR 3 register
Proc _Set_Tmr3(_reg As Word)
		TMR3H = _reg.HB  'Reloads the high byte
		TMR3L = _reg.LB  'Reloads the low byte
		PIR2.TMR3IF = 0  'Flash overflow to zero
End Proc
'Reloads the TMR 5 register
Proc _Set_Tmr5(_reg As Word)
		TMR5H = _reg.HB  'Reloads the high byte
		TMR5L = _reg.LB  'Reloads the low byte
		PIR5.TMR5IF = 0  'Flash overflow to zero
End Proc
'Returns the TMR 1 register
Function _Get_Tmr1() As Word
	_Get_Tmr1.LB = TMR1L  'Loads the low byte
	_Get_Tmr1.HB = TMR1H  'Loads the high byte
End Function
'Returns the TMR 3 register
Function _Get_Tmr3() As Word
	_Get_Tmr1.LB = TMR3L  'Loads the low byte
	_Get_Tmr1.HB = TMR3H  'Loads the high byte
End Function
'Returns the TMR 5 register
Function _Get_Tmr5() As Word
	_Get_Tmr1.LB = TMR5L  'Loads the low byte
	_Get_Tmr1.HB = TMR5H  'Loads the high byte
End Function
'***************************************************
'***************************************************
'TIMER0
'***************************************************
Symbol _TMR0IF = INTCON.TMR0IF  'Flash overflow
'T0CON: TMR0ON T08BIT T0CS T0SE PSA TOPS<2:0>
'Constants for the T0CON register
Const _TMR0_ON =              %10000000  'Timer0 enabled
Const _TMR0_OFF =             %00000000  'Timer0 disabled
Const _TMR0_MODE_8BIT =       %01000000  'Timer0 in 8-bit mode
Const _TMR0_MODE_16BIT =      %00000000  'Timer0 in 16-bit mode
Const _TMR0_EXTERNAL =        %00100000  'External clock source for Timer0
Const _TMR0_INTERNAL =        %00000000  'Internal clock source for Timer0
Const _TMR0_HIGH_TO_LOW =     %00010000  'Increment on high to low transition for external clock
Const _TMR0_LOW_TO_HIGH =     %00000000  'Increment on low to high transition for external clock
Const _TMR0_PS_NOT_ASSIGNED = %00001000  'Prescaler not assigned to Timer0
Const _TMR0_PS_ASSIGNED =     %00000000  'Prescaler assigned to Timer0
'Prescaler values, from 1:2 to 1:256
Const _TMR0_PS_1_2 =   %00000000          '1:2 Prescale value
Const _TMR0_PS_1_4 =   %00000001          '1:4 Prescale value
Const _TMR0_PS_1_8 =   %00000010          '1:8 Prescale value
Const _TMR0_PS_1_16 =  %00000011          '1:16 Prescale value
Const _TMR0_PS_1_32 =  %00000100          '1:32 Prescale value
Const _TMR0_PS_1_64 =  %00000101          '1:64 Prescale value
Const _TMR0_PS_1_128 = %00000110          '1:128 Prescale value
Const _TMR0_PS_1_256 = %00000111          '1:256 Prescale value
'Function to configure the T0CON register
Proc _SetUp_TMR0(_mode As Byte)
    T0CON = _mode
End Proc
'Clears the TMR register
Proc _Clear_TMR0_8Bit()
	TMR0 = 0  'Clears the TMR0 counter
	INTCON.TMR0IF = 0  'Flash overflow to zero
End Proc'Clears the TMR register
Proc _Clear_TMR0_16Bit()
	TMR0H = 0  'Clears the TMR0 counter
	TMR0L = 0  'Clears the TMR0 counter
	INTCON.TMR0IF = 0  'Flash overflow to zero
End Proc
'Reloads the TMR register
Proc _Set_TMR0_8Bit(_reg As Byte)
	TMR0 = _reg  'Assigns value to the TMR0 counter
	INTCON.TMR0IF = 0  'Flash overflow to zero
End Proc
'Reloads the TMR register
Proc _Set_TMR0_16Bit(_reg As Word)
	TMR0H = _reg.HB
	TMR0L = _reg.LB  'Assigns value to the TMR0 counter
	INTCON.TMR0IF = 0  'Flash overflow to zero
End Proc
'Returns the TMR register
Function _Get_TMR0_8Bit() As Byte
	_Get_TMR0_8Bit = TMR0  'Assigns the value of the TMR0 counter
End Function'Returns the TMR register
Function _Get_TMR0_16Bit() As Word
	_Get_TMR0_16Bit.LB = TMR0L  'Assigns the value of the TMR0 counter
	_Get_TMR0_16Bit.HB = TMR0H  'Assigns the value of the TMR0 counter
End Function'Activates or stops the timer1 counter
Proc _Tmr0(_On_Off_bit As Bit)
	T0CON.TMR0ON = _On_Off_bit
End Proc
'***************************************************
'***************************************************
'INTERRUPTIONS:
'***************************************************
'Enable/Disable priority mode interrupts
Const _ENABLE_PRIORITY = 1
Const _DISABLE_PRIORITY = 0
Proc _Interrupts_Mode(_type As Bit)
	RCON.IPEN = _type  'Disable priority levels on interrupts
End Proc
Const _GLOBAL_LOW = 1  'Global and peripheral interrupts
Const _GLOBAL_HIGH = 11
Const _INT_RDA = 2  'Usart Rx interrupt
Const _INT_RDA1 = 2
Const _INT_RDA2 = 12
Const _INT_TMR0 = 0  'TIMER0 interrupt
Const _INT_TMR1 = 3  'TIMER1 interrupt
Const _INT_TMR2 = 4  'TIMER2 interrupt
Const _INT_EXT = 5  'External Interrupt by pulse or edge
Const _INT_RB = 6  'External Interrupt by state change on pins RB7:4
Const _INT_ON_CHANGE_RB4 = 7  'Interruption_on_change Pin RB4 notice
Const _INT_ON_CHANGE_RB5 = 8  'Interruption_on_change Pin RB5 notice
Const _INT_ON_CHANGE_RB6 = 9  'Interruption_on_change Pin RB6 notice
Const _INT_ON_CHANGE_RB7 = 10  'Interruption_on_change Pin RB7 notice
'Activates selected interrupts
Proc _Enable_Interrupts(_int As Byte)
	If _int = 1 Then Enable Low  'INTCON.GIEL enables the global Low interrupts
	If _int = 11 Then Enable High  'INTCON.GIEH enables the global High interrupts
	If _int = 1 Then INTCON.PEIE = 1  'Bit enables peripheral interrupts
	If _int = 11 Then INTCON.PEIE = 1
	If _int = 0 Then INTCON.TMR0IE = 1  'Activates the TIMER0 interrupt
	If _int = 5 Then INTCON.INT0IE = 1  'Activates the EXTERNAL interrupt
	If _int = 6 Then INTCON.RBIE = 1  'Activates the interrupt for change in RB7:4
	If _int = 3 Then PIE1.TMR1IE = 1  'Activates the TIMER1 interrupt
	If _int = 4 Then PIE1.TMR2IE = 1  'Activates the TIMER2 interrupt
	If _int = 2 Then PIE1.RC1IE = 1  'Activates the uart1 interrupt in rx mode*/
	If _int = 12 Then PIE3.RC2IE = 1  'Activates the uart2 interrupt in rx mode*/
	If _int = 7 Then IOCB.4 = 1  'IOCB4 'Activates the external pin change interrupt RB4
	If _int = 8 Then IOCB.5 = 1  'IOCB5 'Activates the external pin change interrupt RB5
	If _int = 9 Then IOCB.6 = 1  'IOCB6 'Activates the external pin change interrupt RB6
	If _int = 10 Then IOCB.7 = 1 'IOCB7 'Activates the external pin change interrupt RB7
End Proc
'Deactivates selected interrupts
Proc _Disable_Interrupts(_int As Byte)
	If _int = 1 Then Disable Low  'INTCON.GIEL disables the global Low interrupts
	If _int = 11 Then Disable High  'INTCON.GIEH disables the global High interrupts
	If _int = 1 Then INTCON.PEIE = 0  'Bit to disable peripheral interrupts
	If _int = 11 Then INTCON.PEIE = 0
	If _int = 0 Then INTCON.TMR0IE = 0  'Disables the TIMER0 interrupt
	If _int = 5 Then INTCON.INT0IE = 0  'Disables the EXTERNAL interrupt
	If _int = 6 Then INTCON.RBIE = 0  'Disables the interrupt for change in RB7:4
	If _int = 3 Then PIE1.TMR1IE = 0  'Disables the TIMER1 interrupt
	If _int = 4 Then PIE1.TMR2IE = 0  'Disables the TIMER2 interrupt
	If _int = 2 Then PIE1.RC1IE = 0  'Disables the uart1 interrupt in rx mode*/
	If _int = 12 Then PIE3.RC2IE = 0  'Disables the uart2 interrupt in rx mode*/
	If _int = 7 Then IOCB.4 = 0  'IOCB4 'Deactivates the external pin change interrupt RB4
	If _int = 8 Then IOCB.5 = 0  'IOCB5 'Deactivates the external pin change interrupt RB5
	If _int = 9 Then IOCB.6 = 0  'IOCB6 'Deactivates the external pin change interrupt RB6
	If _int = 10 Then IOCB.7 = 0 'IOCB7 'Deactivates the external pin change interrupt RB7
End Proc
'******************************************************************************
'******************************************************************************
'Configuration of the INTCON2 register: interrupts and pull-up resistances
'******************************************************************************
' Constants for the bits of the INTCON2 register
'INTCON2: INTERRUPT CONTROL 2 REGISTER: RBPU INTEDG0 INTEDG1 INTEDG2 â€” TMR0IP â€” RBIP
Const PORTB_PULLUP_DISABLE = 0b10000000 '_RBPU: Control of pull-up for PORTB
Const EXT_INT0_EDGE_SELECT = 0b01000000 'INTEDG0: High edge selection for external interrupt 0
Const EXT_INT1_EDGE_SELECT = 0b00100000 'INTEDG1: High edge selection for external interrupt 1
Const EXT_INT2_EDGE_SELECT = 0b00010000 'INTEDG2: High edge selection for external interrupt 2
Const TMR0_OVERFLOW_PRIORITY = 0b00000100 'TMR0IP: Interrupt priority for TMR0 overflow
Const RB_PORT_CHANGE_PRIORITY = 0b00000001 'RBIP: Interrupt priority for port B change
' Procedure to configure the parameters of interrupt control and pull_up.
Proc SetUp_InterruptControl_2(_register As Byte)
    INTCON2 = _register
End Proc
'Activates or deactivates the PullUp resistances of port B
Const _PULLUP_ON = 0
Const _PULLUP_OFF = 1
Proc _Set_PullUp_PortB(_mode As Bit)
	INTCON2.RBPU = _mode  '_RBPU, Enable/Disable PORTB pullups
End Proc
''******************************************************************************
''******************************************************************************
''WATCHDOG (WDT):
''Functions for controlling the WDT module
''******************************************************************************
'Work mode and divider are configured using the Configuration Bits.
'*******************************************************************************
'' Constants for WDTPS (Watchdog Timer Postscale Select) configuration
'Const _WDT_PS_32768 = %111100  ' Postscaler 1:32768
'Const _WDT_PS_16384 = %111000  ' Postscaler 1:16384
'Const _WDT_PS_8192  = %110100  ' Postscaler 1:8192
'Const _WDT_PS_4096  = %110000  ' Postscaler 1:4096
'Const _WDT_PS_2048  = %101100  ' Postscaler 1:2048
'Const _WDT_PS_1024  = %101000  ' Postscaler 1:1024
'Const _WDT_PS_512   = %100100  ' Postscaler 1:512
'Const _WDT_PS_256   = %100000  ' Postscaler 1:256
'Const _WDT_PS_128   = %011100  ' Postscaler 1:128
'Const _WDT_PS_64    = %011000  ' Postscaler 1:64
'Const _WDT_PS_32    = %010100  ' Postscaler 1:32
'Const _WDT_PS_16    = %010000  ' Postscaler 1:16
'Const _WDT_PS_8     = %001100  ' Postscaler 1:8
'Const _WDT_PS_4     = %001000  ' Postscaler 1:4
'Const _WDT_PS_2     = %000100  ' Postscaler 1:2
'' Constants for WDTEN (Watchdog Timer Enable) configuration
'Const _WDT_HW_ENABLED    = %11 ' WDT enabled in hardware; SWDTEN bit disabled
'Const _WDT_SW_CONTROLLED = %10 ' WDT controlled by the SWDTEN bit
'Const _WDT_ACTIVE_ONLY   = %01 ' WDT enabled when active, disabled in Sleep; SWDTEN bit disabled.
'Const _WDTEN_HW_DISABLED = %00 ' WDT disabled in hardware; SWDTEN bit disabled
'' Configures WDT: CONFIG2H
''Example: Call SetUP_WDT(_WDT_SW_CONTROLLED | _WDT_PS_4096)
''		  Call Set_WDT_ON()
Function _SetUp_WDT(_config2h As Byte) As Byte
	''#define CONFIG2H = _WDT_SW_CONTROLLED | _WDT_PS_4096 '_config2h
'    'Pointer(44) = _config2h
'    ReturnValue _config2h
End Function
'Activates the WDT by software (if the WDT fuse is activated, it is ignored)
Proc _Set_WDT_ON()
	WDTCON.SWDTEN = 1
End Proc
'Stops the WDT by software (if the WDT fuse is activated, it is ignored)
Proc _Set_WDT_OFF()
	WDTCON.SWDTEN = 0
End Proc
Proc _Restart_WDT()
	ASM:        CLRWDT  'Resets the WDT
End Proc
'******************************************************************************
'******************************************************************************
'OSCCON: OSCILLATOR CONTROL REGISTER
'******************************************************************************
' Definitions of constants for the OSCCON register
' OSCCON register constants definitions
Const _OSC_16MHz_HF =   %01110000    ' Sets internal oscillator frequency to 16 MHz (HFINTOSC)
Const _OSC_8MHz_HF =    %01100000    ' Sets internal oscillator frequency to 8 MHz (HFINTOSC/2)
Const _OSC_4MHz_HF =    %01010000    ' Sets internal oscillator frequency to 4 MHz (HFINTOSC/4)
Const _OSC_2MHz_HF =    %01000000    ' Sets internal oscillator frequency to 2 MHz (HFINTOSC/8)
Const _OSC_1MHz_HF =    %00110000    ' Sets internal oscillator frequency to 1 MHz (HFINTOSC/16)
'Low frequency (there are more modes with the same frequency using: OSCCON2.MFIOSEL and OSCTUNE.INTSRC).
Const _OSC_500KHz_HF =  %00100000    ' Sets internal oscillator low frequency (HFINTOSC/32)
Const _OSC_250KHz_HF =  %00010000    ' Sets internal oscillator low frequency (HFINTOSC/64)
Const _OSC_31250Hz_HF = %00000000    ' Sets internal oscillator low frequency (LFINTOSC)
'General configuration
Const IDLE_ENABLE =         %10000000    ' Enables Idle mode with the SLEEP instruction
Const OSC_STARTUP_BY_FOSC = %00001000   ' Indicates device running from clock defined by FOSC<3:0>
Const OSC_HF_STABLE =       %00000100  ' Indicates HFINTOSC frequency is stable
Const INTERNAL_OSC_SELECT = %00000001 ' Selects internal oscillator as system clock source
Const PRIMARY_OSC_SELECT =  %00000000 ' Selects primary clock (defined by FOSC<3:0>) as system clock source
'Configures the type of oscillator and operating frequency
Proc _Setup_Oscillator(_register As Byte)
	OSCCON = _register
End Proc
'******************************************************************************
'Software activation of PLL (define fuses)
'******************************************************************************
'Software PLL enable bit (if fuse PLLEN = 0)
Const _PLL_ON = 1
Const _PLL_OFF = 0
Proc _SET_PLL4(_bit As Bit)
	OSCTUNE.PLLEN = _bit
End Proc
'******************************************************************************
'Finetune osc
'******************************************************************************
'Predefined values for _finetune:
	Const _Osc_Adjust_Max = %011111 'Maximum frequency
	'011110 =
	'......
	'000001 =
	Const _Osc_Adjust_Factory = %000000 'Oscillator module is running at the factory-calibrated
	'111111 =
	'......
	Const _Osc_Adjust_Min = %100000 'Minimum frequency
Proc _Setup_Oscillator_Finetune(_finetune As Byte)
	OSCTUNE.TUN0 = _finetune.0
	OSCTUNE.TUN1 = _finetune.1
	OSCTUNE.TUN2 = _finetune.2
	OSCTUNE.TUN3 = _finetune.3
	OSCTUNE.TUN4 = _finetune.4
	OSCTUNE.TUN5 = _finetune.5
End Proc
'*******************************************************************************
'*******************************************************************************
' Procedure to enable or disable a specific analog input (ANx)
' Parameters:
'   n_AN: Analog channel number (from 0 to 27).
'   set: Logical value (0 to disable, 1 to enable).
Proc Set_AN(n_AN As Byte, set As Bit)
    ' Configuration for ANSELA pins (port A)
    If n_AN = 0 Then ANSELA.0 = set ' Channel AN0 on RA0
    If n_AN = 1 Then ANSELA.1 = set ' Channel AN1 on RA1
    If n_AN = 2 Then ANSELA.2 = set ' Channel AN2 on RA2
    If n_AN = 3 Then ANSELA.3 = set ' Channel AN3 on RA3
    If n_AN = 4 Then ANSELA.5 = set ' Channel AN4 on RA5

    ' Configuration for ANSELE pins (port E)
    If n_AN = 5 Then ANSELE.0 = set ' Channel AN5 on RE0
    If n_AN = 6 Then ANSELE.1 = set ' Channel AN6 on RE1
    If n_AN = 7 Then ANSELE.2 = set ' Channel AN7 on RE2

    ' Configuration for ANSELB pins (port B)
    If n_AN = 8 Then ANSELB.2 = set ' Channel AN8 on RB2
    If n_AN = 9 Then ANSELB.3 = set ' Channel AN9 on RB3
    If n_AN = 10 Then ANSELB.1 = set ' Channel AN10 on RB1
    If n_AN = 11 Then ANSELB.4 = set ' Channel AN11 on RB4
    If n_AN = 12 Then ANSELB.0 = set ' Channel AN12 on RB0
    If n_AN = 13 Then ANSELB.5 = set ' Channel AN13 on RB5

    ' Configuration for ANSELC pins (port C)
    If n_AN = 14 Then ANSELC.2 = set ' Channel AN14 on RC2
    If n_AN = 15 Then ANSELC.3 = set ' Channel AN15 on RC3
    If n_AN = 16 Then ANSELC.4 = set ' Channel AN16 on RC4
    If n_AN = 17 Then ANSELC.5 = set ' Channel AN17 on RC5
    If n_AN = 18 Then ANSELC.6 = set ' Channel AN18 on RC6
    If n_AN = 19 Then ANSELC.7 = set ' Channel AN19 on RC7

    ' Configuration for ANSELD pins (port D)
    If n_AN = 20 Then ANSELD.0 = set ' Channel AN20 on RD0
    If n_AN = 21 Then ANSELD.1 = set ' Channel AN21 on RD1
    If n_AN = 22 Then ANSELD.2 = set ' Channel AN22 on RD2
    If n_AN = 23 Then ANSELD.3 = set ' Channel AN23 on RD3
    If n_AN = 24 Then ANSELD.4 = set ' Channel AN24 on RD4
    If n_AN = 25 Then ANSELD.5 = set ' Channel AN25 on RD5
    If n_AN = 26 Then ANSELD.6 = set ' Channel AN26 on RD6
    If n_AN = 27 Then ANSELD.7 = set ' Channel AN27 on RD7
End Proc

'*****************************************************************************************
'SLRCON
'*****************************************************************************************
'Hardware-based limitation of signal transition speed (slew rate) from low to
'High And High To Low.
'Enabled by default (Smoothing enabled on the waveform).

'The SLRCON register contains one Bit for each of the five I/O ports.
'This register only affects the waveform when the pin is configured as an Output.
'It’s important to note that when one or more bits are set To 0, the slew rate
'control hardware is disabled. Conversely, when the bits are set To 1, the
'hardware that smooths the Output waveform is enabled.

'When enabled, the slew rate control limits the speed of the rising edge,
'resulting in A more rounded waveform And reduced electromagnetic interference (EMI).
'On the other hand, when this limitation is disabled (Bit = 0), the rising edge
'becomes sharper, which can improve performance on High-speed buses such As SPI
'by allowing higher clock frequencies, though it may also increase EMI And System noise.
Proc _SlewRate(_bt As Byte)
	If _bt = 0 Then
		SLRCON = 0 'High speed.
	Else
		SLRCON = %11111 'Low speed (Enabled by default).
	Endif
End Proc
'******************************************************************************
'******************************************************************************
'Memory address assignment for working with pointers
'******************************************************************************
'Pointer assignment Pic18 (2023)
'ASM:    LFSR 2, List
'P_List = _PointerWord()
Function _PointerWord() As Word
	Symbol _Return_HB = _PointerWord.HB
	Symbol _Return_LB = _PointerWord.LB
	ASM:		MOVFW FSR2H
	ASM:		MOVWF _Return_HB
	ASM:		MOVFW FSR2L
	ASM:		MOVWF _Return_LB
End Function

'(Obsolete) Function For automatic Pointer assignment.
'By COS, 11/11.
'Basic of the Pic Simulator IDE (PSI).
'*************************************************
'Minimum length of arrays is 2 bytes.
'The starting and ending addresses of the Pic's RAM must be indicated.
'Execute at the beginning.
'*************************************************
'Example (Main):
'Dim X(10) As Byte  'Declares an array.
'Dim P_X As Word  'Declares a pointer always of type Word.
'X(0) = 0xaa  'Key for locating the variable in memory.
'X(1) = 0xaa  'Key for locating the variable in memory.
'P_X = _pointer(0xaa)  'Assigns the address of the variable and search key.
'------------------------------------------------------------------------------
'Pic16F628A Ram 0x20 to 0x14f
'Pic16F88 Ram 0x20 to 0x1ef
'Pic16F877A Ram 0x20 to 0x1ef
'Pic18F26K22 Ram 0x000 to 0xF37
'-------------------------------------------------
'Returns the address of an array.
'The minimum elements that the array can have are two.
Const _P_RAM_START = 0x000  'Start of the RAM for Pic18F26K22
Const _P_RAM_END = 0xF37  'End of the RAM for Pic18F26K22
Function _Address(_key As Byte) As Word
	Dim _dr0_ram As Word  'Address of byte 0
	Dim _dr1_ram As Word  'Address of byte 1
	Dim _dt0 As Byte  'Content of address byte 0
	Dim _dt1 As Byte  'Content of address byte 1
	For _dr0_ram = _P_RAM_START To _P_RAM_END  'Search routine
		_dr1_ram = _dr0_ram + 1
		_dt0 = Pointer(_dr0_ram)  'Assignment of content of address
		_dt1 = Pointer(_dr1_ram)  'Assignment of content of address
		If _dt0 = _key And _dt1 = _key Then  'Comparison
			_Address = _dr0_ram  'Assignment of address
			Pointer(_dr0_ram) = 0  'Initializes the variable
			Pointer(_dr1_ram) = 0
			Exit  'Exits the function
		Endif
		If _dt1 <> _key Then _dr0_ram = _dr1_ram  'Accelerates the search
	Next _dr0_ram
End Function
'********************************************************************************
'********************************************************************************
'Button Function.
'By COS, 31/03/2024, Pic18 Basic Compiler (PSI).
'********************************************************************************
'_portAddress: chosen port.
'_pin: pin of the chosen port (0 to 7, the pin has to be configured as a digital input).
'_ActiveState: state that the key has to have to be validated (0 or 1).
'_Button: returns 0 if no key is pressed and 255 if it is.
'_delay: if the key was validated and remains pressed, generates a delay.
'---------------------------------------------------------------------------------
'Example:
'In Main: If _Button_INT > 0 Then Toggle Led: _Button_INT = 0: Endif
'In the interrupts every 1mSec: _Button_INT(_BUTTON_PORTC, 1, 0, 200)
'Example without interrupts (Main): If _Button1_INT(_BUTTON_PORTC, 0, 0, 100) > 0 Then Toggle Led	Endif
'----------------------------------------------------------------------------------
Const _BUTTON_PORTA = 0XF80 'Address of PORTA
Const _BUTTON_PORTB = 0xF81
Const _BUTTON_PORTC = 0xF82
Const _BUTTON_PORTD = 0xF83
Const _BUTTON_PORTE = 0xF84
'Version for use with interrupts
Function _Button_INT(_portAddress As Word, _pin As Byte, _activeState As Bit, _delay As Byte) As Byte
	Dim _port As Byte
	Dim _n As Byte
	Dim _timeOut As Byte
	'_Button_INT = 0 'Activate for use without interrupts.
	If _timeOut > 0 Then 'Waiting time after reading a key
		_timeOut--
		'WaitUs 1000 'Activate for use without interrupts.
	Else
		If _activeState = Pointer(_portAddress)._pin Then 'If the key is pressed
			_Button_INT = 255
			_timeOut = _delay
		Endif
	Endif
End Function
'*******************************************************************************
