PeripheralPinSelect
NOTE: the PPS.bas module is now included as part of the standard libraries as of V2.2.3.0
This module allows you to assign the remappable input and output pins for devices that have a Peripheral Pin Select (PPS) module.
Currently, the PPS module is only present in certain "J" and "K" series devices, and the number of pins/function varies depending on the device, so consult the datasheet.
Rev History
V1.5 adds support for xxQ10 family and corrects some K40 assignments
V1.41 errata for 24K40/25K40
V1.4 adds support for the xxK40 family
V1.3 added support for the J94/J99 family
Sample Code
device = 18F47J53 include "pps.bas" // //------------------------------------------------------------------------------ // example usage - 47J53 //------------------------------------------------------------------------------ // sub init_pps() // unlock pps registers for change (disables interrupts) pps.unlock() // assign intr pins pps.assign_input(PPS_INT1, PPS_IN_RP3) // INT1 -> RB0 pps.assign_input(PPS_INT3, PPS_IN_RP6) // INT3 -> RB3 // assign uart2 pins pps.assign_input(PPS_RX2, PPS_IN_RP24) // RX2 -> RD7 pps.assign_output(PPS_TX2, PPS_OUT_RP23) // TX2 <- RD6 // assign spi2 (master) pps.assign_output(PPS_SCK2, PPS_OUT_RP20) // SCK2 <- RD3 pps.assign_input(PPS_SDI2, PPS_IN_RP21) // SDI2 -> RD4 pps.assign_output(PPS_SDO2, PPS_OUT_RP22) // SDO2 <- RD5 // relock pps config (restores interrupt enable) pps.lock() end sub // start of main code main: // reset all the pps assignments to default pps.assign_defaults() init_pps()
PPS Module
// //------------------------------------------------------------------------------ // Name : pps.bas // Author : Jerry Messina // Date : 7/22/2018 // Version : 1.50 // Notes : Peripheral Pin Select (PPS) module // : This peripheral is available in select J, K, and Q series devices // : (see PPS module type definitions below for a list of supported devices) // // ver 1.50: change 24K40,25K40 output mapping to match datasheet 40001843D (PPS_V5_1) // : add support for 24Q10,25Q10 (PPS_V6_1) // : add prelim support for 26Q10,27Q10,45Q10,46Q10,47Q10 (PPS_V6_2) // ver 1.41: incorporate output register mapping errata for 24K40/25K40 (PPS_V5_1) // ver 1.4 : add support for xxK40 family // : this family is slightly different so check assign_input/assign_output // : examples // : fix errors from xc8 pps.h for 4xJ50 // ver 1.3 : add support for J94/J99 (PPS_V4) PPS Lite module // : split PPS_V3 into two groups (J13 and J53 devices are different) // : change pin definitions from previous version to support V4 // : add #option PPS_IOL1WAY to enable changes to the config w/out editing // : fix errors from XC8 pps.h // ver 1.2 : add definitions for PPS_V3 RP17/RP18 pins //------------------------------------------------------------------------------ // module pps // //------------------------------------------------------------------------------ // PPS module type definitions // list of devices is current as of MPLABX v4.10 (MPASMX 5.77) // V1.4 adds the K40 family (PPS_V5 devices), which are not supported by XC8 plibs // V1.5 adds the Q10 family (PPS_V6 devices) // notes: // taken from XC8 v1.33 pconfig.h/pps.h (and C18 v3.47) // note: pconfig.h lumps the J13 and J53 devices together into PPS_V3, but they // have to be split into two groups (V3 and V3B) because of RPOR14/15/16 // also, some of the mappings in pps.h aren't correct, esp for the V4 devices // (V4 devices don't work at all in XC8) //------------------------------------------------------------------------------ // #if _device in (18F24J50, 18F25J50, 18F26J50) #define PPS_V1 #elseif _device in (18F24J11, 18F25J11, 18F26J11) #define PPS_V1_1 #elseif _device in (18F44J50, 18F45J50, 18F46J50) #define PPS_V2 #elseif _device in (18F44J11, 18F45J11, 18F46J11) #define PPS_V2_1 #elseif _device in (18F26J13, 18F27J13) #define PPS_V3 #elseif _device in (18F26J53, 18F27J53) #define PPS_V3B #elseif _device in (18F46J13, 18F47J13) #define PPS_V3_1 #elseif _device in (18F46J53, 18F47J53) #define PPS_V3B_1 #elseif _device in (18F65J94, 18F66J94, 18F67J94) or _ _device in (18F85J94, 18F86J94, 18F87J94, 18F95J94, 18F96J94, 18F97J94) or _ _device in (18F66J99, 18F86J99, 18F96J99) #define PPS_V4 #elseif _device in (18F24K40, 18F25K40, 18LF24K40, 18LF25K40) #define PPS_V5_1 #elseif _device in (18F26K40, 18F27K40, 18LF26K40, 18LF27K40) #define PPS_V5_1B #elseif _device in (18F45K40, 18F46K40, 18F47K40, 18LF45K40, 18LF46K40, 18LF47K40) #define PPS_V5_2 #elseif _device in (18F65K40, 18F66K40, 18F67K40, 18LF65K40, 18LF66K40, 18LF67K40) #define PPS_V5_3 #elseif _device in (18F24Q10, 18F25Q10) #define PPS_V6_1 #elseif _device in (18F26Q10, 18F45Q10, 18F46Q10, 18F27Q10, 18F47Q10) #define PPS_V6_2 #else #error _device + " unknown PPS module type" #endif // //------------------------------------------------------------------------------ // PPS CONFIG settings //------------------------------------------------------------------------------ // // There is a CONFIG bit (IOL1WAY/PPS1WAY) that will prevent you from changing // the pps mapping more than once, and it defaults to ON. You must set the config // setting off if you want to be able to remap them more than once #option PPS_IOL1WAY = OFF // K40 device #if defined(PPS_V5_1) or defined(PPS_V5_1B) or defined(PPS_V5_2) or defined(PPS_V5_3) config PPS1WAY = PPS_IOL1WAY // Q10 device #elseif defined(PPS_V6_1) or defined(PPS_V6_2) config PPS1WAY = PPS_IOL1WAY // all others #else config IOL1WAY = PPS_IOL1WAY #endif // the lock() and unlock() sequences are timing sensitive. by default, the routines // will manage the state of the global IE bit... lock() will disable interrupts and // unlock() will restore the setting that was in effect when lock() was initially // called. setting 'PPS_DISABLE_INT = false' will bypass this #option PPS_DISABLE_INT = true // //------------------------------------------------------------------------------ // PPS input //------------------------------------------------------------------------------ // // pps input pin definitions #if defined (PPS_V1) or defined (PPS_V1_1) or defined (PPS_V2) or defined (PPS_V2_1) or _ defined (PPS_V3) or defined (PPS_V3_1) or defined (PPS_V3B) or defined (PPS_V3B_1) public const PPS_IN_VSS = 31 // RPxx Input tied to Vss (unused) public const PPS_IN_RP0 = 0 // assign RP0 as Input Pin public const PPS_IN_RP1 = 1 // assign RP1 as Input Pin public const PPS_IN_RP2 = 2 // assign RP2 as Input Pin public const PPS_IN_RP3 = 3 // assign RP3 as Input Pin public const PPS_IN_RP4 = 4 // assign RP4 as Input Pin public const PPS_IN_RP5 = 5 // assign RP5 as Input Pin public const PPS_IN_RP6 = 6 // assign RP6 as Input Pin public const PPS_IN_RP7 = 7 // assign RP7 as Input Pin public const PPS_IN_RP8 = 8 // assign RP8 as Input Pin public const PPS_IN_RP9 = 9 // assign RP9 as Input Pin public const PPS_IN_RP10 = 10 // assign RP10 as Input Pin public const PPS_IN_RP11 = 11 // assign RP11 as Input Pin public const PPS_IN_RP12 = 12 // assign RP12 as Input Pin public const PPS_IN_RP13 = 13 // assign RP13 as Input Pin // alias name for unmapping an input pin public const PPS_IN_UNUSED = PPS_IN_VSS #endif // (PPS_V1) or (PPS_V1_1) or (PPS_V2) or (PPS_V2_1) or (PPS_V3) or (PPS_V3_1) or (PPS_V3B) or (PPS_V3B_1) #if defined (PPS_V1_1) or defined (PPS_V2_1) public const PPS_IN_RP14 = 14 // assign RP14 as Input Pin public const PPS_IN_RP15 = 15 // assign RP15 as Input Pin public const PPS_IN_RP16 = 16 // assign RP16 as Input Pin #endif // (PPS_V1_1) or (PPS_V2_1) #if defined (PPS_V1) or defined (PPS_V2) or defined (PPS_V2_1) or defined (PPS_V3_1) or defined (PPS_V3B_1) public const PPS_IN_RP17 = 17 // assign RP17 as Input Pin public const PPS_IN_RP18 = 18 // assign RP18 as Input Pin #endif // (PPS_V1) or (PPS_V2) or (PPS_V2_1) or (PPS_V3_1) or (PPS_V3B_1) #if defined (PPS_V2) or defined (PPS_V2_1) or defined (PPS_V3_1) or defined (PPS_V3B_1) public const PPS_IN_RP19 = 19 // assign RP19 as Input Pin public const PPS_IN_RP20 = 20 // assign RP20 as Input Pin public const PPS_IN_RP21 = 21 // assign RP21 as Input Pin public const PPS_IN_RP22 = 22 // assign RP22 as Input Pin public const PPS_IN_RP23 = 23 // assign RP23 as Input Pin public const PPS_IN_RP24 = 24 // assign RP24 as Input Pin #endif // (PPS_V2) or (PPS_V2_1) or (PPS_V3_1) or (PPS_V3B_1) #if defined (PPS_V4) public const PPS_IN_VSS = $0F // RPxx Input tied to Vss (unused) // GROUP 4n public const PPS_IN_RP0 = 0 // assign RP0 as Input Pin public const PPS_IN_RP4 = 1 // assign RP1 as Input Pin public const PPS_IN_RP8 = 2 // assign RP2 as Input Pin public const PPS_IN_RP12 = 3 // assign RP3 as Input Pin public const PPS_IN_RP16 = 4 // assign RP4 as Input Pin public const PPS_IN_RP20 = 5 // assign RP5 as Input Pin public const PPS_IN_RP24 = 6 // assign RP6 as Input Pin public const PPS_IN_RP28 = 7 // assign RP7 as Input Pin public const PPS_IN_RP32 = 8 // assign RP8 as Input Pin public const PPS_IN_RP36 = 9 // assign RP9 as Input Pin public const PPS_IN_RP40 = $0A // assign RP10 as Input Pin public const PPS_IN_RP44 = $0B // assign RP11 as Input Pin // GROUP (4n+1) public const PPS_IN_RP1 = 0 // assign RP0 as Input Pin public const PPS_IN_RP5 = 1 // assign RP1 as Input Pin public const PPS_IN_RP9 = 2 // assign RP2 as Input Pin public const PPS_IN_RP13 = 3 // assign RP3 as Input Pin public const PPS_IN_RP17 = 4 // assign RP4 as Input Pin public const PPS_IN_RP21 = 5 // assign RP5 as Input Pin public const PPS_IN_RP25 = 6 // assign RP6 as Input Pin public const PPS_IN_RP29 = 7 // assign RP7 as Input Pin public const PPS_IN_RP33 = 8 // assign RP8 as Input Pin public const PPS_IN_RP37 = 9 // assign RP9 as Input Pin public const PPS_IN_RP41 = $0A // assign RP10 as Input Pin public const PPS_IN_RP45 = $0B // assign RP11 as Input Pin // GROUP (4n+2) public const PPS_IN_RP2 = 0 // assign RP0 as Input Pin public const PPS_IN_RP6 = 1 // assign RP1 as Input Pin public const PPS_IN_RP10 = 2 // assign RP2 as Input Pin public const PPS_IN_RP14 = 3 // assign RP3 as Input Pin public const PPS_IN_RP18 = 4 // assign RP4 as Input Pin public const PPS_IN_RP22 = 5 // assign RP5 as Input Pin public const PPS_IN_RP26 = 6 // assign RP6 as Input Pin public const PPS_IN_RP30 = 7 // assign RP7 as Input Pin public const PPS_IN_RP34 = 8 // assign RP8 as Input Pin public const PPS_IN_RP38 = 9 // assign RP9 as Input Pin public const PPS_IN_RP42 = $0A // assign RP10 as Input Pin public const PPS_IN_RP46 = $0B // assign RP11 as Input Pin // GROUP (4n+3) public const PPS_IN_RP3 = 0 // assign RP0 as Input Pin public const PPS_IN_RP7 = 1 // assign RP1 as Input Pin public const PPS_IN_RP11 = 2 // assign RP2 as Input Pin public const PPS_IN_RP15 = 3 // assign RP3 as Input Pin public const PPS_IN_RP19 = 4 // assign RP4 as Input Pin public const PPS_IN_RP23 = 5 // assign RP5 as Input Pin public const PPS_IN_RP27 = 6 // assign RP6 as Input Pin public const PPS_IN_RP31 = 7 // assign RP7 as Input Pin public const PPS_IN_RP35 = 8 // assign RP8 as Input Pin public const PPS_IN_RP39 = 9 // assign RP9 as Input Pin public const PPS_IN_RP43 = $0A // assign RP10 as Input Pin public const PPS_IN_RP47 = $0B // assign RP11 as Input Pin // alias name for unmapping an input pin public const PPS_IN_UNUSED = PPS_IN_VSS #endif // (PPS_V4) // pps input functions #if defined (PPS_V1) or defined (PPS_V1_1) or defined (PPS_V2) or defined (PPS_V2_1) or _ defined (PPS_V3) or defined (PPS_V3_1) or defined (PPS_V3B) or defined (PPS_V3B_1) public dim PPS_INT1 as RPINR1 // assign External Interrupt 1 (INTR1) to the RPn pin public dim PPS_INT2 as RPINR2 // assign External Interrupt 2 (INTR2) to the RPn pin public dim PPS_INT3 as RPINR3 // assign External Interrupt 3 (INTR3) to the RPn pin public dim PPS_T0CK as RPINR4 // assign Timer0 External Clock (T0CK) to the RPn pin public dim PPS_T3CK as RPINR6 // assign Timer3 External Clock (T3CK) to the RPn pin public dim PPS_IC1 as RPINR7 // assign Input Capture 1 (IC1) to the RPn pin public dim PPS_IC2 as RPINR8 // assign Input Capture 2 (IC2) to the RPn pin public dim PPS_T1G as RPINR12 // assign Timer1 External Gate Input (TG1) to the RPn pin public dim PPS_T3G as RPINR13 // assign Timer3 External Gate Input (TG3) to the RPn pin public dim PPS_RX2 as RPINR16 // assign EUSART2 Async/Sync Receive (RX2/DT2) to the RPn pin public dim PPS_CK2 as RPINR17 // assign EUSART2 Sync Slave Clock Input (CK2) to the RPn pin public dim PPS_SDI2 as RPINR21 // assign SDI2 Data Input (SDI2) to the RPn pin public dim PPS_SCK2IN as RPINR22 // assign SCK2 Clock Input (SCK2IN) to the RPn pin public dim PPS_SS2IN as RPINR23 // assign SS2 Slave Select Input (SS2IN) to the RPn pin public dim PPS_FLT0 as RPINR24 // assign PWM Fault Input (FLT0) to the RPn pin #endif // (PPS_V1) or (PPS_V1_1) or (PPS_V2) or (PPS_V2_1) od (PPS_V3) or (PPS_V3_1) or (PPS_V3B) or (PPS_V3B_1) #if defined (PPS_V3) or defined (PPS_V3_1) or defined (PPS_V3B) or defined (PPS_V3B_1) public dim PPS_T5CK as RPINR15 // assign Timer5 External Clock (T5CK) to the RPn pin public dim PPS_IC3 as RPINR9 // assign Input Capture 3 (IC3) to the RPn pin public dim PPS_T5G as RPINR14 // assign Timer5 External Gate Input (TG5) to the RPn pin #endif // (PPS_V3) or (PPS_V3_1) or (PPS_V3B_1) // the PPS Lite module splits the RPINR registers into two nibbles with certain functions // assigned to each of the upper and lower nibbles. in order to use a macro for this we need // a unique value for each input function so that we can place the setting in the proper spot. // we just assign numbers to the functions in increasing order... the number itself isn't // important as the macro will translate PPS_xxx input functions to RPINRxx registers // some input function names had to be changed so that there is a unique input/output function // (ie PPS_CCPx, PPS_PBIOx, etc) // #if defined (PPS_V4) // GROUP 4n public const PPS_SDI1 = 0 // assign SDI1 Data input (SDI1) to the RPn pin public const PPS_FLT0 = 1 // assign PWM Fault Input (FLT0) to the RPn pin public const PPS_IOC0 = 2 // assign InterruptOnChange0 (IOC0) to the RPn pin public const PPS_IOC4 = 3 // assign InterruptOnChange4 (IOC4) to the RPn pin public const PPS_MDCIN1 = 4 // assign MDCIN1 to the RPn pin public const PPS_T0CKI = 5 // assign Timer0 External Clock (T0CKI) to the RPn pin public const PPS_T5G = 6 // assign Timer5 External Gate Input (T5G) to the RPn pin public const PPS_U3RX = 7 // assign EUSART3 Async/Sync Receive (RX3/DT3) to the RPn pin public const PPS_U4RX = 8 // assign EUSART4 Async/Sync Receive (RX4/DT4) to the RPn pin public const PPS_IC5 = 9 // assign Input Capture 5 (CCP5) to the RPn pin public const PPS_IC8 = 10 // assign Input Capture 8 (CCP8) to the RPn pin public const PPS_PBI0 = 11 // assign PBIO0 to the RPn pin (Virtual port?) public const PPS_PBI4 = 12 // assign PBIO4 to the RPn pin // GROUP (4n+1) public const PPS_SDI2 = 13 // assign SDI1 Data input (SDI2) to the RPn pin public const PPS_INT1 = 14 // assign External Interrupt 1 (INTR1) to the RPn pin public const PPS_IOC1 = 15 // assign InterruptOnChange1 (IOC1) to the RPn pin public const PPS_IOC5 = 16 // assign InterruptOnChange5 (IOC5) to the RPn pin public const PPS_MDCIN2 = 17 // assign MDCIN2 to the RPn pin public const PPS_T1CKI = 18 // assign Timer1 External Clock (T1CKI) to the RPn pin public const PPS_T1G = 19 // assign Timer1 External Gate Input (T1G) to the RPn pin public const PPS_T3CKI = 20 // assign Timer3 External Clock (T3CKI) to the RPn pin public const PPS_T3G = 21 // assign Timer3 External Gate Input (T3G) to the RPn pin public const PPS_T5CKI = 22 // assign Timer5 External Clock (T5CKI) to the RPn pin public const PPS_U3TX_CKI = 23 // assign EUSART3 Sync Clock In (TX3/CK3) to the RPn pin public const PPS_U4TX_CKI = 24 // assign EUSART4 Sync Clock In (TX4/CK4) to the RPn pin public const PPS_IC7 = 25 // assign Input Capture 7 (CCP7) to the RPn pin public const PPS_IC9 = 26 // assign Input Capture 9 (CCP9) to the RPn pin public const PPS_PBI1 = 27 // assign PBIO1 to the RPn pin public const PPS_PBI5 = 28 // assign PBIO5 to the RPn pin // GROUP (4n+2) public const PPS_SS1 = 29 // assign SS1 (SS1) to the RPn pin public const PPS_INT2 = 30 // assign External Interrupt 2 (INTR2) to the RPn pin public const PPS_IOC2 = 31 // assign InterruptOnChange2 (IOC2) to the RPn pin public const PPS_IOC6 = 32 // assign InterruptOnChange6 (IOC6) to the RPn pin public const PPS_MDMIN = 33 // assign MDMIN to the RPn pin public const PPS_U1TX_CKI = 34 // assign EUSART1 Sync Clock In (TX1/CK1) to the RPn pin public const PPS_U2RX = 35 // assign EUSART2 Async/Sync Receive (RX2/DT2) to the RPn pin public const PPS_SCK2IN = 36 // assign SCK2 to the RPn pin public const PPS_ECCP3 = 37 // assign ECCP3 to the RPn pin public const PPS_IC6 = 38 // assign Input Capture 6 (CCP6) to the RPn pin public const PPS_IC10 = 39 // assign Input Capture 10 (CCP10) to the RPn pin public const PPS_PBI2 = 40 // assign PBIO2 to the RPn pin public const PPS_PBI6 = 41 // assign PBIO6 to the RPn pin // GROUP (4n+3) public const PPS_SS2 = 42 // assign SS2 (SS2) to the RPn pin public const PPS_INT3 = 43 // assign External Interrupt 3 (INTR3) to the RPn pin public const PPS_IOC3 = 44 // assign InterruptOnChange3 (IOC3) to the RPn pin public const PPS_IOC7 = 45 // assign InterruptOnChange7 (IOC7) to the RPn pin public const PPS_U1RX = 46 // assign EUSART1 Async/Sync Receive (RX1/DT1) to the RPn pin public const PPS_U2TX_CKI = 47 // assign EUSART2 Sync Clock In (TX2/CK2) to the RPn pin public const PPS_SCK1IN = 48 // assign SCK1 to the RPn pin public const PPS_ECCP1 = 49 // assign ECCP1 to the RPn pin public const PPS_ECCP2 = 50 // assign ECCP2 to the RPn pin public const PPS_IC4 = 51 // assign Input Capture 4 (CCP4) to the RPn pin public const PPS_PBI3 = 52 // assign PBIO2 to the RPn pin public const PPS_PBI7 = 53 // assign PBIO6 to the RPn pin #endif // (PPS_V4) // K40 family device #if defined(PPS_V5_1) or defined(PPS_V5_1B) or defined(PPS_V5_2) or defined(PPS_V5_3) // Register Definitions: PPS Input Selection // xxxPPS<4:3> Peripheral xxx Input PORTx Selection bits public const PPS_PORTA as byte = %0000, PPS_PORTB as byte = %0001, PPS_PORTC as byte = %0010 // 18(L)F4xK40, 18(L)F6xK40 #if defined(PPS_V5_2) or defined(PPS_V5_3) public const PPS_PORTD as byte = %0011 #endif // 4xK40, 6xK40 // 18(L)F6xK40 #if defined(PPS_V5_3) public const PPS_PORTE as byte = %0100, PPS_PORTF as byte = %0101, PPS_PORTG as byte = %0110, PPS_PORTH as byte = %0111 #endif // 6xK40 // xxxPPS<2:0>: Peripheral xxx Input PINx Pin Selection bits // pin selection bits are three bits 0-7, ie port pin 0(Rx0) = 0, port pin 7(Rx7) = 7 // xxxPPS<4:3>: Peripheral xxx Input PORTx Pin Selection bits // port selection bits are four bits 0-3: 0000=PORTA, 0001=PORTB, 0010=PORTC, 0011=PORTD, etc // K40 family // assign_input(input_function_reg, pps_port, pin_no) // // assigns pps input function to a pin // input_function_reg pps input register/function (ie INT0PPS) from datasheet TABLE 17-1 // pps_port one of PPS_PORTA to PPS_PORTH definitions above // pin_no port pin number 0-7 // // to assign an input function to a pin set xxxPPS reg input PORT bits[4:3] and PIN bits[2:0]: // xxxPPS = (PPS_PORTx << 3) + (port_pin_no and %111) // macro example: // pps.assign_input(INT0PPS, PPS_PORTA, 4) // assigns INT0 input to RA4 // pps.assign_input(RX1PPS, PPS_PORTB, 2) // assigns usart RX1 input to RB2 // note: pps input functions are limited to specific ports // currently the macro does not check to see if the assignment is valid (nothing does) // refer to TABLE 17-1: PPS INPUT REGISTER DETAILS in the device datasheet for specifics // public macro assign_input(pps_function_reg, pps_port, pin_no) pps_function_reg = ((pps_port and %0111) << 3) + (pin_no and %111) end macro // Q10 family device #elseif defined(PPS_V6_1) or defined(PPS_V6_2) // Register Definitions: PPS Input Selection // xxxPPS<4:3> Peripheral xxx Input PORTx Selection bits public const PPS_PORTA as byte = %0000, PPS_PORTB as byte = %0001, PPS_PORTC as byte = %0010 // 18F4xQ10 #if _device in(18F45Q10, 18F46Q10, 18F47Q10) public const PPS_PORTD as byte = %0011 #endif // 4xQ10 // xxxPPS<2:0>: Peripheral xxx Input PINx Pin Selection bits // pin selection bits are three bits 0-7, ie port pin 0(Rx0) = 0, port pin 7(Rx7) = 7 // xxxPPS<4:3>: Peripheral xxx Input PORTx Pin Selection bits // port selection bits are two bits 0-1: 00=PORTA, 01=PORTB, 10=PORTC, 11=PORTD // Q10 family (similar to K40) // assign_input(input_function_reg, pps_port, pin_no) // // assigns pps input function to a pin // input_function_reg pps input register/function (ie INT0PPS) from datasheet TABLE 17-1 // pps_port one of PPS_PORTA to PPS_PORTD definitions above // pin_no port pin number 0-7 // // to assign an input function to a pin set xxxPPS reg input PORT bits[4:3] and PIN bits[2:0]: // xxxPPS = (PPS_PORTx << 3) + (port_pin_no and %111) // macro example: // pps.assign_input(INT0PPS, PPS_PORTA, 4) // assigns INT0 input to RA4 // pps.assign_input(RX1PPS, PPS_PORTB, 2) // assigns usart RX1 input to RB2 // note: pps input functions are limited to specific ports // currently the macro does not check to see if the assignment is valid (nothing does) // refer to TABLE 17-1: PPS INPUT REGISTER DETAILS in the device datasheet for specifics // public macro assign_input(pps_function_reg, pps_port, pin_no) pps_function_reg = ((pps_port and %0111) << 3) + (pin_no and %111) end macro // J94/J99 family #elseif defined(PPS_V4) //------------------------------------------------------------------------------ // assign_input(input_fn, rp_pin) // // assigns pps input function to a pin // input_fn input function/register (ie PPS_RX2) // rp_pin PPS_IN_RPx pin (ie PPS_IN_RP0) // example usage: // assign_input(PPS_INT1, PPS_IN_UNUSED) 'unmaps INT1 function // assign_input(PPS_RX2, PPS_IN_RP0) 'sets RPINR16 to RP0 pin // //------------------------------------------------------------------------------ public macro assign_input(input_fn, rp_pin) // for the PPS Lite module we need to translate input "function numbers" // to register and upper/lower nibble selection. just do it brute force // since the macro will remove all the unused code // taken from J94/J99 family datasheet Table 11-12 // functions that use the lower nibble of the RPINRxx reg if (input_fn = PPS_PBI6) then RPINR52_53 = (RPINR52_53 and $F0) or rp_pin elseif (input_fn = PPS_PBI4) then RPINR50_51 = (RPINR50_51 and $F0) or rp_pin elseif (input_fn = PPS_PBI2) then RPINR48_49 = (RPINR48_49 and $F0) or rp_pin elseif (input_fn = PPS_PBI0) then RPINR46_47 = (RPINR46_47 and $F0) or rp_pin elseif (input_fn = PPS_T5G) then RPINR44_45 = (RPINR44_45 and $F0) or rp_pin elseif (input_fn = PPS_T3G) then RPINR42_43 = (RPINR42_43 and $F0) or rp_pin elseif (input_fn = PPS_T1G) then RPINR40_41 = (RPINR40_41 and $F0) or rp_pin elseif (input_fn = PPS_IC10) then RPINR38_39 = (RPINR38_39 and $F0) or rp_pin elseif (input_fn = PPS_IC8) then RPINR36_37 = (RPINR36_37 and $F0) or rp_pin elseif (input_fn = PPS_IC6) then RPINR34_35 = (RPINR34_35 and $F0) or rp_pin elseif (input_fn = PPS_IC4) then RPINR32_33 = (RPINR32_33 and $F0) or rp_pin elseif (input_fn = PPS_MDCIN1) then RPINR30_31 = (RPINR30_31 and $F0) or rp_pin elseif (input_fn = PPS_INT3) then RPINR28_29 = (RPINR28_29 and $F0) or rp_pin elseif (input_fn = PPS_INT1) then RPINR26_27 = (RPINR26_27 and $F0) or rp_pin elseif (input_fn = PPS_IOC6) then RPINR24_25 = (RPINR24_25 and $F0) or rp_pin elseif (input_fn = PPS_IOC4) then RPINR22_23 = (RPINR22_23 and $F0) or rp_pin elseif (input_fn = PPS_IOC2) then RPINR20_21 = (RPINR20_21 and $F0) or rp_pin elseif (input_fn = PPS_IOC0) then RPINR18_19 = (RPINR18_19 and $F0) or rp_pin elseif (input_fn = PPS_ECCP2) then RPINR16_17 = (RPINR16_17 and $F0) or rp_pin elseif (input_fn = PPS_FLT0) then RPINR14_15 = (RPINR14_15 and $F0) or rp_pin elseif (input_fn = PPS_SDI2) then RPINR12_13 = (RPINR12_13 and $F0) or rp_pin elseif (input_fn = PPS_SS1) then RPINR10_11 = (RPINR10_11 and $F0) or rp_pin elseif (input_fn = PPS_SCK1IN) then RPINR8_9 = (RPINR8_9 and $F0) or rp_pin elseif (input_fn = PPS_U4RX) then RPINR6_7 = (RPINR6_7 and $F0) or rp_pin elseif (input_fn = PPS_U3RX) then RPINR4_5 = (RPINR4_5 and $F0) or rp_pin elseif (input_fn = PPS_U2RX) then RPINR2_3 = (RPINR2_3 and $F0) or rp_pin elseif (input_fn = PPS_U1RX) then RPINR0_1 = (RPINR0_1 and $F0) or rp_pin endif // functions that use the upper nibble of the RPINRxx reg if (input_fn = PPS_U1TX_CKI) then RPINR0_1 = (RPINR0_1 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_U2TX_CKI) then RPINR2_3 = (RPINR2_3 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_U3TX_CKI) then RPINR4_5 = (RPINR4_5 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_U4TX_CKI) then RPINR6_7 = (RPINR6_7 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_SDI1) then RPINR8_9 = (RPINR8_9 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_SCK2IN) then RPINR10_11 = (RPINR10_11 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_SS2) then RPINR12_13 = (RPINR12_13 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_ECCP1) then RPINR14_15 = (RPINR14_15 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_ECCP3) then RPINR16_17 = (RPINR16_17 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_IOC1) then RPINR18_19 = (RPINR18_19 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_IOC3) then RPINR20_21 = (RPINR20_21 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_IOC5) then RPINR22_23 = (RPINR22_23 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_IOC7) then RPINR24_25 = (RPINR24_25 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_INT2) then RPINR26_27 = (RPINR26_27 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_MDMIN) then RPINR28_29 = (RPINR28_29 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_MDCIN2) then RPINR30_31 = (RPINR30_31 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_IC5) then RPINR32_33 = (RPINR32_33 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_IC7) then RPINR34_35 = (RPINR34_35 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_IC9) then RPINR36_37 = (RPINR36_37 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_T0CKI) then RPINR38_39 = (RPINR38_39 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_T1CKI) then RPINR40_41 = (RPINR40_41 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_T3CKI) then RPINR42_43 = (RPINR42_43 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_T5CKI) then RPINR44_45 = (RPINR44_45 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_PBI1) then RPINR46_47 = (RPINR46_47 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_PBI3) then RPINR48_49 = (RPINR48_49 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_PBI5) then RPINR50_51 = (RPINR50_51 and $0F) or (rp_pin << 4) elseif (input_fn = PPS_PBI7) then RPINR52_53 = (RPINR52_53 and $0F) or (rp_pin << 4) endif end macro // regular V1-V3 PPS module #else public macro assign_input(input_rp_reg, rp_pin) input_rp_reg = rp_pin end macro #endif // PPS_V5/PPS_V4/PPS_V1-PPS_V3 // //------------------------------------------------------------------------------ // PPS output //------------------------------------------------------------------------------ // // pps output functions #if defined (PPS_V1) or defined (PPS_V2) or defined (PPS_V1_1) or defined (PPS_V2_1) or _ defined (PPS_V3) or defined (PPS_V3_1) or defined (PPS_V3B) or defined (PPS_V3B_1) public const PPS_NULL = 0 // RPn tied to default port pin public const PPS_C1OUT = 1 // RPn tied to comparator 1 output public const PPS_C2OUT = 2 // RPn tied to comparator 2 output public const PPS_ULPWU = 13 // RPn tied to Ultra Low Power Wake Up Event public const PPS_CCP1P1A = 14 // RPn tied to ECCP1/CCP1 compare or PWM output channel A public const PPS_P1B = 15 // RPn tied to ECCP1 Enhanced PWM output, channel B public const PPS_P1C = 16 // RPn tied to ECCP1 Enhanced PWM output, channel C public const PPS_P1D = 17 // RPn tied to ECCP1 Enhanced PWM output, channel D public const PPS_CCP2P2A = 18 // RPn tied to ECCP2/CCP2 compare or PWM output public const PPS_P2B = 19 // RPn tied to ECCP2 Enhanced PWM output, channel B public const PPS_P2C = 20 // RPn tied to ECCP2 Enhanced PWM output, channel C public const PPS_P2D = 21 // RPn tied to ECCP2 Enhanced PWM output, channel D // alias name for unmapping an output pin public const PPS_OUT_UNUSED = PPS_NULL #endif // (PPS_V1) or (PPS_V2) or (PPS_V1_1) or (PPS_V2_1) or (PPS_V3) or (PPS_V3_1) or (PPS_V3B) or (PPS_V3B_1) #if defined (PPS_V1) or defined (PPS_V2) or defined (PPS_V1_1) or defined (PPS_V2_1) public const PPS_TX2CK2 = 5 // RPn tied to EUSART 2 Async Transmit / Sync Clock Output public const PPS_TX2 = 5 // alias for PPS_TX2CK2 public const PPS_DT2 = 6 // RPn tied to EUSART 2 Sync Transmit public const PPS_SDO2 = 9 // RPn tied to SPI2 Data Output public const PPS_SCK2 = 10 // RPn tied to SPI2 Clock Output public const PPS_SSDMA = 12 // RPn tied to SPI DMA Slave Select #endif // (PPS_V1) or (PPS_V2) or (PPS_V1_1) or (PPS_V2_1) #if defined (PPS_V3) or defined (PPS_V3_1) or defined (PPS_V3B) or defined (PPS_V3B_1) public const PPS_C3OUT = 3 // RPn tied to comparator 3 output public const PPS_TX2CK2 = 6 // RPn tied to EUSART 2 Async Transmit / Sync Clock Output public const PPS_TX2 = 6 // alias for PPS_TX2CK2 public const PPS_DT2 = 7 // RPn tied to EUSART 2 Sync Transmit public const PPS_SDO2 = 10 // RPn tied to SPI2 Data Output public const PPS_SCK2 = 11 // RPn tied to SPI2 Clock Output public const PPS_SSDMA = 12 // RPn tied to SPI DMA Slave Select public const PPS_CCP3P3A = 22 // RPn tied to ECCP3/CCP3 compare or PWM output public const PPS_P3B = 23 // RPn tied to ECCP3 Enhanced PWM output, channel B public const PPS_P3C = 24 // RPn tied to ECCP3 Enhanced PWM output, channel C public const PPS_P3D = 25 // RPn tied to ECCP3 Enhanced PWM output, channel D #endif // (PPS_V3) or (PPS_V3_1) or (PPS_V3B) or (PPS_V3B_1) #if defined (PPS_V4) // some output function names had to be changed so that there is a unique input/output function // (ie PPS_CCPx, PPS_PBIOx, etc) public const PPS_NULL = 0 // RPn tied to default port pin // alias name for unmapping an output pin public const PPS_OUT_UNUSED = PPS_NULL // GROUP 4n public const PPS_U2BCLK = 1 // RPn tied to U2BCLK port pin public const PPS_U3RX_DT = 2 // RPn tied to EUSART3 Sync transmit (RX3/DT3) output public const PPS_U4RX_DT = 3 // RPn tied to EUSART4 Sync transmit (TRX4/DT4) output public const PPS_SDO2 = 4 // RPn tied to SPI2 Data Output public const PPS_P1D = 5 // RPn tied to ECCP1 Enhanced PWM output, channel D public const PPS_P2D = 6 // RPn tied to ECCP2 Enhanced PWM output, channel D public const PPS_P3B = 7 // RPn tied to ECCP3 Enhanced PWM output, channel B public const PPS_CTPLS = 8 // RPn tied to CTPLS public const PPS_CCP5 = 9 // RPn tied to CCP5 compare or PWM output public const PPS_CCP8 = $0A // RPn tied to CCP8 compare or PWM output public const PPS_C1OUT = $0B // RPn tied to comparator 1 public const PPS_PBO0 = $0D // RPn tied to PBIO0 public const PPS_PBO4 = $0E // RPn tied to PBIO4 // GROUP (4n+1) public const PPS_U1BCLK = 1 // RPn tied to U1BCLK port pin public const PPS_U3TX_CK = 2 // RPn tied to EUSART3 Async Transmit / sync Clock Output public const PPS_U3TX = PPS_U3TX_CK public const PPS_U4TX_CK = 3 // RPn tied to EUSART4 Async Transmit / sync Clock Output public const PPS_U4TX = PPS_U4TX_CK public const PPS_SDO1 = 4 // RPn tied to SPI1 Data Output public const PPS_P1C = 5 // RPn tied to ECCP1 Enhanced PWM output, channel C public const PPS_P2C = 6 // RPn tied to ECCP2 Enhanced PWM output, channel C public const PPS_P3C = 7 // RPn tied to ECCP3 Enhanced PWM output, channel C public const PPS_CCP7 = 8 // RPn tied to CCP7 compare or PWM output public const PPS_CCP9 = 9 // RPn tied to CCP9 compare or PWM output public const PPS_C2OUT = $0A // RPn tied to comparator 2 public const PPS_PBO1 = $0D // RPn tied to PBIO1 public const PPS_PBO5 = $0E // RPn tied to PBIO5 // GROUP (4n+2) public const PPS_U1TX_CK = 1 // RPn tied to EUSART1 Async Transmit / sync Clock Output public const PPS_U1TX = PPS_U1TX_CK public const PPS_U2RX_DT = 2 // RPn tied to EUSART2 Async/Sync Receive (RX2/DT2) public const PPS_U3BCLK = 3 // RPn tied to U3BCLK port pin public const PPS_U4BCLK = 4 // RPn tied to U4BCLK port pin public const PPS_SCK2 = 5 // RPn tied to SPI2 Clock Output public const PPS_P1B = 6 // RPn tied to ECCP1 Enhanced PWM output, channel B public const PPS_P2B = 7 // RPn tied to ECCP2 Enhanced PWM output, channel B public const PPS_ECCP3P3A = 8 // RPn tied to ECCP3/CCP3 compare or PWM output public const PPS_CCP6 = 9 // RPn tied to CCP6 compare or PWM output public const PPS_CCP10 = $0A // RPn tied to CCP10 compare or PWM output public const PPS_PBO2 = $0D // RPn tied to PBIO2 public const PPS_PBO6 = $0E // RPn tied to PBIO6 // GROUP (4n+3) public const PPS_U1RX_DT = 1 // RPn tied to EUSART1 Async/sync Receive (RX1/DT1) public const PPS_U2TX_CK = 2 // RPn tied to EUSART2 Async Transmit / sync Clock Output public const PPS_U2TX = PPS_U2TX_CK public const PPS_SCK1 = 3 // RPn tied to SPI1 Clock Output public const PPS_ECCP1P1A = 4 // RPn tied to ECCP1/CCP1 compare or PWM output public const PPS_ECCP2P2A = 5 // RPn tied to ECCP2/CCP2 compare or PWM output public const PPS_P3D = 6 // RPn tied to ECCP3 Enhanced PWM output, channel D public const PPS_MDOUT = 7 // RPn tied to MDOUT port pin public const PPS_CCP4 = 8 // RPn tied to CCP4 compare or PWM output public const PPS_C3OUT = 9 // RPn tied to comparator 3 public const PPS_PBO3 = $0D // RPn tied to PBIO3 public const PPS_PBO7 = $0E // RPn tied to PBIO7 #endif // (PPS_V4) // pps output pin definitions #if defined (PPS_V1) or defined (PPS_V2) or defined (PPS_V1_1) or defined (PPS_V2_1) or _ defined (PPS_V3) or defined (PPS_V3_1) or defined (PPS_V3B) or defined (PPS_V3B_1) public dim PPS_OUT_RP0 as RPOR0 // assign RP0 as Output Pin public dim PPS_OUT_RP1 as RPOR1 // assign RP1 as Output Pin public dim PPS_OUT_RP2 as RPOR2 // assign RP2 as Output Pin public dim PPS_OUT_RP3 as RPOR3 // assign RP3 as Output Pin public dim PPS_OUT_RP4 as RPOR4 // assign RP4 as Output Pin public dim PPS_OUT_RP5 as RPOR5 // assign RP5 as Output Pin public dim PPS_OUT_RP6 as RPOR6 // assign RP6 as Output Pin public dim PPS_OUT_RP7 as RPOR7 // assign RP7 as Output Pin public dim PPS_OUT_RP8 as RPOR8 // assign RP8 as Output Pin public dim PPS_OUT_RP9 as RPOR9 // assign RP9 as Output Pin public dim PPS_OUT_RP10 as RPOR10 // assign RP10 as Output Pin public dim PPS_OUT_RP11 as RPOR11 // assign RP11 as Output Pin public dim PPS_OUT_RP12 as RPOR12 // assign RP12 as Output Pin public dim PPS_OUT_RP13 as RPOR13 // assign RP13 as Output Pin public dim PPS_OUT_RP17 as RPOR17 // assign RP17 as Output Pin public dim PPS_OUT_RP18 as RPOR18 // assign RP18 as Output Pin #endif // (PPS_V1) or (PPS_V2) or (PPS_V1_1) or (PPS_V2_1) or (PPS_V3) or (PPS_V3_1) or (PPS_V3B) or (PPS_V3B_1) #if defined (PPS_V1_1) or defined (PPS_V2_1) or defined (PPS_V3) or defined (PPS_V3_1) public dim PPS_OUT_RP14 as RPOR14 // assign RP14 as Output Pin public dim PPS_OUT_RP15 as RPOR15 // assign RP15 as Output Pin public dim PPS_OUT_RP16 as RPOR16 // assign RP16 as Output Pin #endif // (PPS_V1_1) or (PPS_V2_1) or (PPS_V3) or (PPS_V3_1) #if defined (PPS_V2) or defined (PPS_V2_1) or defined (PPS_V3_1) or defined (PPS_V3B_1) public dim PPS_OUT_RP19 as RPOR19 // assign RP19 as Output Pin public dim PPS_OUT_RP20 as RPOR20 // assign RP20 as Output Pin public dim PPS_OUT_RP21 as RPOR21 // assign RP21 as Output Pin public dim PPS_OUT_RP22 as RPOR22 // assign RP22 as Output Pin public dim PPS_OUT_RP23 as RPOR23 // assign RP23 as Output Pin public dim PPS_OUT_RP24 as RPOR24 // assign RP24 as Output Pin #endif // (PPS_V2) or (PPS_V2_1) or (PPS_V3_1) or (PPS_V3B_1) // the PPS Lite module splits the RPOR registers into two nibbles with certain pins // assigned to each of the upper and lower nibbles. in order to use a macro for this we need // a unique value for each output pin so that we can place the setting in the proper spot. // we just assign numbers to the output pins to match the RPx number... the number itself // isn't important as the macro will translate PPS_OUT_RPxx pins to RPORx registers #if defined (PPS_V4) // GROUP 4n public const PPS_OUT_RP0 = 0 // assign RP0 as Output Pin public const PPS_OUT_RP4 = 4 // assign RP4 as Output Pin public const PPS_OUT_RP8 = 8 // assign RP8 as Output Pin public const PPS_OUT_RP12 = 12 // assign RP12 as Output Pin public const PPS_OUT_RP16 = 16 // assign RP16 as Output Pin public const PPS_OUT_RP20 = 20 // assign RP20 as Output Pin public const PPS_OUT_RP24 = 24 // assign RP24 as Output Pin public const PPS_OUT_RP28 = 28 // assign RP28 as Output Pin public const PPS_OUT_RP32 = 32 // assign RP32 as Output Pin public const PPS_OUT_RP36 = 36 // assign RP36 as Output Pin public const PPS_OUT_RP40 = 40 // assign RP40 as Output Pin public const PPS_OUT_RP44 = 44 // assign RP44 as Output Pin // GROUP (4n+1) public const PPS_OUT_RP1 = 1 // assign RP1 as Output Pin public const PPS_OUT_RP5 = 5 // assign RP5 as Output Pin public const PPS_OUT_RP9 = 9 // assign RP9 as Output Pin public const PPS_OUT_RP13 = 13 // assign RP13 as Output Pin public const PPS_OUT_RP17 = 17 // assign RP17 as Output Pin public const PPS_OUT_RP21 = 21 // assign RP21 as Output Pin public const PPS_OUT_RP25 = 25 // assign RP25 as Output Pin public const PPS_OUT_RP29 = 29 // assign RP29 as Output Pin public const PPS_OUT_RP33 = 33 // assign RP33 as Output Pin public const PPS_OUT_RP37 = 37 // assign RP37 as Output Pin public const PPS_OUT_RP41 = 41 // assign RP41 as Output Pin public const PPS_OUT_RP45 = 45 // assign RP45 as Output Pin // GROUP (4n+2) public const PPS_OUT_RP2 = 2 // assign RP2 as Output Pin public const PPS_OUT_RP6 = 6 // assign RP6 as Output Pin public const PPS_OUT_RP10 = 10 // assign RP10 as Output Pin public const PPS_OUT_RP14 = 14 // assign RP14 as Output Pin public const PPS_OUT_RP18 = 18 // assign RP18 as Output Pin public const PPS_OUT_RP22 = 22 // assign RP22 as Output Pin public const PPS_OUT_RP26 = 26 // assign RP26 as Output Pin public const PPS_OUT_RP30 = 30 // assign RP30 as Output Pin public const PPS_OUT_RP34 = 34 // assign RP34 as Output Pin public const PPS_OUT_RP38 = 38 // assign RP38 as Output Pin public const PPS_OUT_RP42 = 42 // assign RP42 as Output Pin public const PPS_OUT_RP46 = 46 // assign RP46 as Output Pin // GROUP (4n+3) public const PPS_OUT_RP3 = 3 // assign RP3 as Output Pin public const PPS_OUT_RP7 = 7 // assign RP7 as Output Pin public const PPS_OUT_RP11 = 11 // assign RP11 as Output Pin public const PPS_OUT_RP15 = 15 // assign RP15 as Output Pin public const PPS_OUT_RP19 = 19 // assign RP19 as Output Pin public const PPS_OUT_RP23 = 23 // assign RP23 as Output Pin public const PPS_OUT_RP27 = 27 // assign RP27 as Output Pin public const PPS_OUT_RP31 = 31 // assign RP31 as Output Pin public const PPS_OUT_RP35 = 35 // assign RP35 as Output Pin public const PPS_OUT_RP39 = 39 // assign RP39 as Output Pin public const PPS_OUT_RP43 = 43 // assign RP43 as Output Pin #endif // (PPS_V4) // //---------------------------------------------------------- // PPS output pin assignments //---------------------------------------------------------- // // K40 family #if defined(PPS_V5_1) or defined(PPS_V5_1B) or defined(PPS_V5_2) or defined(PPS_V5_3) // 24K40, 25K40 (see errata DS80000711B pg 6) // v1.50 note: these were changed in datasheet 40001843D #if defined(PPS_V5_1) public const PPS_ADGRDB as byte = $13, PPS_ADGRDA as byte = $14, // was $12 w PPS_DSM as byte = $11, PPS_CLKR as byte = $10, PPS_TMR0 as byte = $0F, PPS_MSSP1_SDO_SDA as byte = $0E, PPS_MSSP1_SCK_SCL as byte = $0D, PPS_CMP2 as byte = $0C, PPS_CMP1 as byte = $0B, PPS_EUSART1_RX as byte = $0A, PPS_EUSART1_TX as byte = $09, PPS_PWM4 as byte = $08, PPS_PWM3 as byte = $07, PPS_CCP2 as byte = $06, PPS_CCP1 as byte = $05, PPS_CWG1D as byte = $04, PPS_CWG1C as byte = $03, PPS_CWG1B as byte = $02, PPS_CWG1A as byte = $01, PPS_LAT as byte = $00, PPS_NULL as byte = PPS_LAT #endif // PPS_5_1 // 26K40, 27K40, 4xK40 #if defined(PPS_V5_1B) or defined(PPS_V5_2) public const PPS_ADGRDB as byte = $17, PPS_ADGRDA as byte = $16, PPS_DSM as byte = $15, PPS_CLKR as byte = $14, PPS_TMR0 as byte = $13, PPS_MSSP2_SDO_SDA as byte = $12, PPS_MSSP2_SCK_SCL as byte = $11, PPS_MSSP1_SDO_SDA as byte = $10, PPS_MSSP1_SCK_SCL as byte = $0F, PPS_CMP2 as byte = $0E, PPS_CMP1 as byte = $0D, PPS_EUSART2_RX as byte = $0C, PPS_EUSART2_TX as byte = $0B, PPS_EUSART1_RX as byte = $0A, PPS_EUSART1_TX as byte = $09, PPS_PWM4 as byte = $08, PPS_PWM3 as byte = $07, PPS_CCP2 as byte = $06, PPS_CCP1 as byte = $05, PPS_CWG1D as byte = $04, PPS_CWG1C as byte = $03, PPS_CWG1B as byte = $02, PPS_CWG1A as byte = $01, PPS_LAT as byte = $00, PPS_NULL as byte = PPS_LAT #endif // PPS_5_1B/5_2 // 6xK40 #if defined(PPS_V5_3) public const PPS_ADGRDB as byte = $21, PPS_ADGRDA as byte = $20, PPS_DSM as byte = $1f, PPS_CLKR as byte = $1e, PPS_TMR0 as byte = $1d, PPS_MSSP2_SDO_SDA as byte = $1c, PPS_MSSP2_SCK_SCL as byte = $1b, PPS_MSSP1_SDO_SDA as byte = $1a, PPS_MSSP1_SCK_SCL as byte = $19, PPS_CMP3 as byte = $18, PPS_CMP2 as byte = $17, PPS_CMP1 as byte = $16, PPS_EUSART5_DT as byte = $15, PPS_EUSART5_RX as byte = $15, PPS_EUSART5_TX_CK as byte = $14, PPS_EUSART5_TX as byte = $14, PPS_EUSART4_DT as byte = $13, PPS_EUSART4_RX as byte = $13, PPS_EUSART4_TX_CK as byte = $12, PPS_EUSART4_TX as byte = $12, PPS_EUSART3_DT as byte = $11, PPS_EUSART3_RX as byte = $11, PPS_EUSART3_TX_CK as byte = $10, PPS_EUSART3_TX as byte = $10, PPS_EUSART2_DT as byte = $0f, PPS_EUSART2_RX as byte = $0f, PPS_EUSART2_TX_CK as byte = $0e, PPS_EUSART2_TX as byte = $0e, PPS_EUSART1_DT as byte = $0d, PPS_EUSART1_RX as byte = $0d, PPS_EUSART1_TX_CK as byte = $0c, PPS_EUSART1_TX as byte = $0c, PPS_PWM7 as byte = $0b, PPS_PWM6 as byte = $0a, PPS_CCP5 as byte = $09, PPS_CCP4 as byte = $08, PPS_CCP3 as byte = $07, PPS_CCP2 as byte = $06, PPS_CCP1 as byte = $05, PPS_CWG1D as byte = $04, PPS_CWG1C as byte = $03, PPS_CWG1B as byte = $02, PPS_CWG1A as byte = $01, PPS_LAT as byte = $00, PPS_NULL as byte = PPS_LAT #endif // PPS_5_3 // // to assign an output function to a pin: // RxxPPS = pps_output_function // macro example: // pps.assign_output(RA0PPS, PPS_TMR0) // assigns TMR0 output to RA0 // pps.assign_output(RB1PPS, PPS_EUSART1_TX) // assigns usart TX1 output to RB1 // note: pps output functions are limited to specific ports // currently the macro does not check to see if the assignment is valid (nothing does) // refer to REGISTER 17-2 PIN Rxy OUTPUT SOURCE SELECTION REGISTER // note: for the K40 family this macro doesn't really do much at all // public macro assign_output(pps_port_sel_reg, pps_out_function) pps_port_sel_reg = pps_out_function end macro // Q10 family #elseif defined(PPS_V6_1) or defined(PPS_V6_2) #if defined(PPS_V6_1) // 24Q10, 25Q10 datasheet DS40001945B public const PPS_ADGRDB as byte = $13, PPS_ADGRDA as byte = $12, // likely a mistake... K40 has this as $14 now PPS_DSM as byte = $11, PPS_CLKR as byte = $10, PPS_TMR0 as byte = $0F, PPS_MSSP1_SDO_SDA as byte = $0E, PPS_MSSP1_SCK_SCL as byte = $0D, PPS_CMP2 as byte = $0C, PPS_CMP1 as byte = $0B, PPS_EUSART1_RX as byte = $0A, PPS_EUSART1_TX as byte = $09, PPS_PWM4 as byte = $08, PPS_PWM3 as byte = $07, PPS_CCP2 as byte = $06, PPS_CCP1 as byte = $05, PPS_CWG1D as byte = $04, PPS_CWG1C as byte = $03, PPS_CWG1B as byte = $02, PPS_CWG1A as byte = $01, PPS_LAT as byte = $00, PPS_NULL as byte = PPS_LAT #endif // PPS_V6_1 // 26Q10, 45Q10, 46Q10, 27Q10, 47Q10 #if defined(PPS_V6_2) public const PPS_CLC8OUT as byte = $1F, PPS_CLC7OUT as byte = $1E, PPS_CLC6OUT as byte = $1D, PPS_CLC5OUT as byte = $1C, PPS_CLC4OUT as byte = $1B, PPS_CLC3OUT as byte = $1A, PPS_CLC2OUT as byte = $19, PPS_CLC1OUT as byte = $18, PPS_ADGRDB as byte = $17, PPS_ADGRDA as byte = $16, PPS_DSM as byte = $15, PPS_CLKR as byte = $14, PPS_TMR0 as byte = $13, PPS_MSSP2_SDO_SDA as byte = $12, PPS_MSSP2_SCK_SCL as byte = $11, PPS_MSSP1_SDO_SDA as byte = $10, PPS_MSSP1_SCK_SCL as byte = $0F, PPS_CMP2 as byte = $0E, PPS_CMP1 as byte = $0D, PPS_EUSART2_RX as byte = $0C, PPS_EUSART2_TX as byte = $0B, PPS_EUSART1_RX as byte = $0A, PPS_EUSART1_TX as byte = $09, PPS_PWM4 as byte = $08, PPS_PWM3 as byte = $07, PPS_CCP2 as byte = $06, PPS_CCP1 as byte = $05, PPS_CWG1D as byte = $04, PPS_CWG1C as byte = $03, PPS_CWG1B as byte = $02, PPS_CWG1A as byte = $01, PPS_LAT as byte = $00, PPS_NULL as byte = PPS_LAT #endif // PPS_V6_2 // // to assign an output function to a pin: // RxxPPS = pps_output_function // macro example: // pps.assign_output(RA0PPS, PPS_TMR0) // assigns TMR0 output to RA0 // pps.assign_output(RB1PPS, PPS_EUSART1_TX) // assigns usart TX1 output to RB1 // note: pps output functions are limited to specific ports // currently the macro does not check to see if the assignment is valid (nothing does) // refer to REGISTER 17-2 PIN Rxy OUTPUT SOURCE SELECTION REGISTER // note: for the Q10 family this macro doesn't really do much at all // public macro assign_output(pps_port_sel_reg, pps_out_function) pps_port_sel_reg = pps_out_function end macro #elseif defined(PPS_V4) //------------------------------------------------------------------------------ // assign_output(output_fn, rp_pin) // // assign pps output function to a pin // output_fn pps output function (ie PPS_TX2) // rp_pin PPS_OUT_RPx pin (ie PPS_OUT_RP0) // example usage: // assign_output(PPS_NULL, PPS_OUT_RP0) // assign_output(PPS_TX2, PPS_OUT_RP23) //------------------------------------------------------------------------------ public macro assign_output(output_fn, rp_pin) // for the PPS Lite module we need to translate output "pin numbers" // to register and upper/lower nibble selection. just do it brute force // since the macro will remove all the unused code // functions that use the lower nibble of the RPORxx reg if (rp_pin = PPS_OUT_RP0) then RPOR0_1 = (RPOR0_1 and $F0) or output_fn elseif (rp_pin = PPS_OUT_RP4) then RPOR4_5 = (RPOR4_5 and $F0) or output_fn elseif (rp_pin = PPS_OUT_RP8) then RPOR8_9 = (RPOR8_9 and $F0) or output_fn elseif (rp_pin = PPS_OUT_RP12) then RPOR12_13 = (RPOR12_13 and $F0) or output_fn elseif (rp_pin = PPS_OUT_RP16) then RPOR16_17 = (RPOR16_17 and $F0) or output_fn elseif (rp_pin = PPS_OUT_RP20) then RPOR20_21 = (RPOR20_21 and $F0) or output_fn elseif (rp_pin = PPS_OUT_RP24) then RPOR24_25 = (RPOR24_25 and $F0) or output_fn elseif (rp_pin = PPS_OUT_RP28) then RPOR28_29 = (RPOR28_29 and $F0) or output_fn elseif (rp_pin = PPS_OUT_RP32) then RPOR32_33 = (RPOR32_33 and $F0) or output_fn elseif (rp_pin = PPS_OUT_RP36) then RPOR36_37 = (RPOR36_37 and $F0) or output_fn elseif (rp_pin = PPS_OUT_RP40) then RPOR40_41 = (RPOR40_41 and $F0) or output_fn elseif (rp_pin = PPS_OUT_RP44) then RPOR44_45 = (RPOR44_45 and $F0) or output_fn elseif (rp_pin = PPS_OUT_RP2) then RPOR2_3 = (RPOR2_3 and $F0) or output_fn elseif (rp_pin = PPS_OUT_RP6) then RPOR6_7 = (RPOR6_7 and $F0) or output_fn elseif (rp_pin = PPS_OUT_RP10) then RPOR10_11 = (RPOR10_11 and $F0) or output_fn elseif (rp_pin = PPS_OUT_RP14) then RPOR14_15 = (RPOR14_15 and $F0) or output_fn elseif (rp_pin = PPS_OUT_RP18) then RPOR18_19 = (RPOR18_19 and $F0) or output_fn elseif (rp_pin = PPS_OUT_RP22) then RPOR22_23 = (RPOR22_23 and $F0) or output_fn elseif (rp_pin = PPS_OUT_RP26) then RPOR26_27 = (RPOR26_27 and $F0) or output_fn elseif (rp_pin = PPS_OUT_RP30) then RPOR30_31 = (RPOR30_31 and $F0) or output_fn elseif (rp_pin = PPS_OUT_RP34) then RPOR34_35 = (RPOR34_35 and $F0) or output_fn elseif (rp_pin = PPS_OUT_RP38) then RPOR38_39 = (RPOR38_39 and $F0) or output_fn elseif (rp_pin = PPS_OUT_RP42) then RPOR42_43 = (RPOR42_43 and $F0) or output_fn elseif (rp_pin = PPS_OUT_RP46) then RPOR46 = (RPOR46 and $F0) or output_fn endif // functions that use the upper nibble of the RPORxx reg if (rp_pin = PPS_OUT_RP1) then RPOR0_1 = (RPOR0_1 and $0F) or (output_fn << 4) elseif (rp_pin = PPS_OUT_RP5) then RPOR4_5 = (RPOR4_5 and $0F) or (output_fn << 4) elseif (rp_pin = PPS_OUT_RP9) then RPOR8_9 = (RPOR8_9 and $0F) or (output_fn << 4) elseif (rp_pin = PPS_OUT_RP13) then RPOR12_13 = (RPOR12_13 and $0F) or (output_fn << 4) elseif (rp_pin = PPS_OUT_RP17) then RPOR16_17 = (RPOR16_17 and $0F) or (output_fn << 4) elseif (rp_pin = PPS_OUT_RP21) then RPOR20_21 = (RPOR20_21 and $0F) or (output_fn << 4) elseif (rp_pin = PPS_OUT_RP25) then RPOR24_25 = (RPOR24_25 and $0F) or (output_fn << 4) elseif (rp_pin = PPS_OUT_RP29) then RPOR28_29 = (RPOR28_29 and $0F) or (output_fn << 4) elseif (rp_pin = PPS_OUT_RP33) then RPOR32_33 = (RPOR32_33 and $0F) or (output_fn << 4) elseif (rp_pin = PPS_OUT_RP37) then RPOR36_37 = (RPOR36_37 and $0F) or (output_fn << 4) elseif (rp_pin = PPS_OUT_RP41) then RPOR40_41 = (RPOR40_41 and $0F) or (output_fn << 4) elseif (rp_pin = PPS_OUT_RP45) then RPOR44_45 = (RPOR44_45 and $0F) or (output_fn << 4) elseif (rp_pin = PPS_OUT_RP3) then RPOR2_3 = (RPOR2_3 and $0F) or (output_fn << 4) elseif (rp_pin = PPS_OUT_RP7) then RPOR6_7 = (RPOR6_7 and $0F) or (output_fn << 4) elseif (rp_pin = PPS_OUT_RP11) then RPOR10_11 = (RPOR10_11 and $0F) or (output_fn << 4) elseif (rp_pin = PPS_OUT_RP15) then RPOR14_15 = (RPOR14_15 and $0F) or (output_fn << 4) elseif (rp_pin = PPS_OUT_RP19) then RPOR18_19 = (RPOR18_19 and $0F) or (output_fn << 4) elseif (rp_pin = PPS_OUT_RP23) then RPOR22_23 = (RPOR22_23 and $0F) or (output_fn << 4) elseif (rp_pin = PPS_OUT_RP27) then RPOR26_27 = (RPOR26_27 and $0F) or (output_fn << 4) elseif (rp_pin = PPS_OUT_RP31) then RPOR30_31 = (RPOR30_31 and $0F) or (output_fn << 4) elseif (rp_pin = PPS_OUT_RP35) then RPOR34_35 = (RPOR34_35 and $0F) or (output_fn << 4) elseif (rp_pin = PPS_OUT_RP39) then RPOR38_39 = (RPOR38_39 and $0F) or (output_fn << 4) elseif (rp_pin = PPS_OUT_RP43) then RPOR42_43 = (RPOR42_43 and $0F) or (output_fn << 4) endif end macro #else // regular V1-V3 PPS module public macro assign_output(output_fn, rp_pin) rp_pin = output_fn end macro #endif // (PPS_V4) // //------------------------------------------------------------------------------ // PPS helper functions //------------------------------------------------------------------------------ // // // unlock/lock pps configuration // Changes to the pps control registers must be unlocked in hardware prior to // accessing them, or they will not change. This should be done with interrupts // disabled, so unlock() records the state of the global IE flag for later use // by the lock() routine // // K40 family #if defined(PPS_V5_1) or defined(PPS_V5_1B) or defined(PPS_V5_2) or defined(PPS_V5_3) dim PPSLOCKED_BIT as PPSLOCK.bits(0) // PPSLOCKED bit dim PPSLOCK_REG as PPSLOCK // alias name for the PPS lock control reg // Q10 family #elseif defined(PPS_V6_1) or defined(PPS_V6_2) dim PPSLOCKED_BIT as PPSLOCK.bits(0) // PPSLOCKED bit dim PPSLOCK_REG as PPSLOCK // alias name for the PPS lock control reg // J94/J99 family #elseif defined (PPS_V4) dim PPSLOCKED_BIT as OSCCON2.bits(6) // IOLOCK bit dim PPSLOCK_REG as WREG // alias name for the (dummy) PPS lock control reg // all others #else dim PPSLOCKED_BIT as PPSCON.bits(0) // IOLOCK bit dim PPSLOCK_REG as EECON2 // alias name for the PPS lock control reg #endif #if (PPS_DISABLE_INT) dim t_intcon as byte // copy of INTCON register const GIE = 7 // GIEH bit number #endif // //------------------------------------------------------------------------------ // unlock PPS configuration changes //------------------------------------------------------------------------------ // public sub unlock() #if (PPS_DISABLE_INT) // save current state of GIE intr bit and disable interrupts t_intcon = INTCON INTCON.bits(GIE) = 0 #endif // send sequence to unlock the PPS configuration PPSLOCK_REG = $55 PPSLOCK_REG = $AA PPSLOCKED_BIT = 0 end sub // //------------------------------------------------------------------------------ // lock PPS configuration //------------------------------------------------------------------------------ // public sub lock() // send sequence to lock the PPS configuration PPSLOCK_REG = $55 PPSLOCK_REG = $AA PPSLOCKED_BIT = 1 #if (PPS_DISABLE_INT) // restore the interrupt enable state previously saved by unlock() if (t_intcon.bits(GIE) = 1) then INTCON.bits(GIE) = 1 endif #endif end sub // //------------------------------------------------------------------------------ // assign_defaults() // remap all RPxx pins to the default unmapped state //------------------------------------------------------------------------------ // // RPINR and RPOR register ranges #if defined (PPS_V1) or defined (PPS_V1_1) or defined(PPS_V3) or defined(PPS_V3B) dim FIRST_RPINR as RPINR1 dim LAST_RPINR as RPINR24 dim FIRST_RPOR as RPOR0 dim LAST_RPOR as RPOR18 #elseif defined (PPS_V2) or defined (PPS_V2_1) or defined (PPS_V3_1) or defined (PPS_V3B_1) dim FIRST_RPINR as RPINR1 dim LAST_RPINR as RPINR24 dim FIRST_RPOR as RPOR0 dim LAST_RPOR as RPOR24 #elseif defined (PPS_V4) dim FIRST_RPINR as RPINR0_1 dim LAST_RPINR as RPINR52_53 dim FIRST_RPOR as RPOR0_1 dim LAST_RPOR as RPOR46 #endif #if defined(PPS_V5_1) or defined(PPS_V5_1B) or defined(PPS_V5_2) or defined(PPS_V5_3) or defined(PPS_V6_1) or defined(PPS_V6_2) public sub assign_defaults() // the K40 and Q10 family do not have a common "default" register setting // it's best to do it individually, so this is just a dummy routine end sub #else public sub assign_defaults() // default setting depends on PPS type... V4 has two settings per reg #if defined (PPS_V4) const RPIN_UNUSED = PPS_IN_UNUSED or (PPS_IN_UNUSED << 4) const RPOUT_UNUSED = PPS_OUT_UNUSED or (PPS_OUT_UNUSED << 4) #else const RPIN_UNUSED = PPS_IN_UNUSED const RPOUT_UNUSED = PPS_OUT_UNUSED #endif dim wtmp as word, // need a word to compute address differences, count as wtmp.bytes(0) // but only need a byte count value result // the algorithm used here relies on a few assumptions: // - registers in the RPINR and RPOR sections are contiguous // - addresses in a section increase from first to last (last > first) // - writing to an unimplemented register causes no harm // if any of these assumptions aren't true then the routine will // have unintended consequences // unlock pps for config changes unlock() // default inputs - tied to PPS_VSS // compute the count of RPINRxx regs to set wtmp = addressof(LAST_RPINR) wtmp = wtmp - addressof(FIRST_RPINR) count = byte(wtmp) + 1 // init starting addr and loop setting RPINRxx FSR0 = addressof(FIRST_RPINR) repeat POSTINC0 = RPIN_UNUSED count = count - 1 until (count = 0) // default outputs - set to default port pin function // compute the count of RPORxx regs to set wtmp = addressof(LAST_RPOR) wtmp = wtmp - addressof(FIRST_RPOR) count = byte(wtmp) + 1 // init starting addr and loop setting RPORxx FSR0 = addressof(FIRST_RPOR) repeat POSTINC0 = RPOUT_UNUSED count = count - 1 until (count = 0) // relock pps lock() end sub #endif // //------------------------------------------------------------------------------ // module initialization //------------------------------------------------------------------------------ // end module