Using the J94 family Virtual Port feature

Coding and general discussion relating to user created compiler modules

Moderators: David Barker, Jerry Messina

Post Reply
Jerry Messina
Swordfish Developer
Posts: 1469
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Using the J94 family Virtual Port feature

Post by Jerry Messina » Sat Feb 14, 2015 3:07 pm

The J94 family has an interesting feature... a user-assignable virtual port that lets you construct a PORT from 8 unrelated pins on the device.

The virtual port (VP) has three control registers just like a normal port: PORTVP, LATVP, and TRISVP. To select which PORT pins are assigned to the VP you use the PPS functions to map RPxx pins to the virtual port registers.

There is one caveat... the PPS Lite module of the J94 has restrictions on which RPxx pins can be mapped to which functions, and divides the mapping into 4 subset groups.

Pretty neat!

Here's an example...

Code: Select all

program vport

// Microchip USB PIM 18F87J94 MA180033
device = 18F87J94
clock = 64

// config settings
// 18F87J94 w/internal FRC osc and PLL
  config
    FOSC     = FRCPLL,    //
    SOSCSEL  = LOW,       // SOSC circuit configured for crystal driver mode
    CLKOEN   = OFF,       // Disable clock output on RA6
    IESO     = OFF,       // Internal External (clock) Switchover
    PLLDIV   = NODIV,     // 4MHz input (from 8MHz FRC/2) provided to PLL circuit
    POSCMD   = NONE,      // Primary osc disabled, using FRC
    FSCM     = CSECMD,    // Clock switching enabled, fail safe clock monitor disabled
    WDTEN    = OFF


// pps module
include "pps.bas"

// Microchip PIM 18F87J94 hardware
dim LED1     as PORTE.0      // LED D1 (red)
dim LED2     as PORTE.1      // LED D2 (red)
dim INPUT_SW as PORTB.4      // sw S4 w/ext 15K pullup (defaults to analog AN0)

// The virtual port (VP) has three control registers just like a normal port:
//      PORTVP, LATVP, and TRISVP
// To select which PORT pins are assigned to the VP you must use the pps 
// PPS_PBI/PPS_PBO functions to map RPxx pins to the virtual port registers.
// The PPS Lite module of the J94 has restrictions on which RPxx pins can be mapped
// to which functions, and divides the mapping into 4 subset groups.
//
// LED1 is RE0_RP28, and RP28 is in peripheral group 4n which can be mapped to PBIO0 or PBIO4
// LED2 is RE1_RP29, and RP29 is in peripheral group 4n+1 which can be mapped to PBIO1 or PBIO5
// INPUT_SW is RB4_RP12, and RP12 is in peripheral group 4n which can be mapped to PBIO0 or PBIO4
//
// with those restrictions in mind, we'll assign the hdw to the following virtual port bits: 
const
    VLED1_BIT       = 4,
    VLED2_BIT       = 5,
    VINPUT_SW_BIT   = 0
    
dim VLED1     as LATVP.bits(VLED1_BIT)      // LED D1 connected to PORTVP.4
dim VLED2     as LATVP.bits(VLED2_BIT)      // LED D2 connected to PORTVP.5
dim VINPUT_SW as PORTVP.bits(VINPUT_SW_BIT)  // sw S4 connected to PORTVP.0


// initIO() - setup IO pins and other req'd regs
sub initIO()
    // all digital (disable A/D on all pins)
    ANCON1 = %00000000
    ANCON2 = %00000000
    ANCON3 = %00000000
    CM1CON = %00000000      ' disable comparators
    CM2CON = %00000000
    CM3CON = %00000000

    // init leds & switch
    low(LED1)
    low(LED2)
    input(INPUT_SW)
end sub

// map physical pins to the virtual port
sub init_virtual_port()
    pps.unlock()

    // map pps pins to PORTVP
    pps.assign_output(PPS_PBO7, PPS_OUT_RP28)
    pps.assign_output(PPS_PBO6, PPS_OUT_RP29)
    pps.assign_input(PPS_PBI0, PPS_IN_RP12)

    pps.lock()
    
    LATVP = 0               // init output pins low
    TRISVP = %00000001      // all outputs except PB0
end sub

main:
initIO()
    
while (true)
    //
    // use regular port pin functions
    //
    pps.assign_defaults()
    LED1 = 1
    LED2 = 0
    // toggle leds until button pressed
    while (INPUT_SW = 1)
        toggle(LED1)
        toggle(LED2)
        delayms(250)
    end while
    LED1 = 1
    LED2 = 1
    // wait for button release
    while (INPUT_SW = 0)
    end while
    LED1 = 0
    LED2 = 0
    
    //
    // control via the virtual port
    //
    init_virtual_port()
    VLED1 = 0
    VLED2 = 1
    // toggle leds until button pressed (but at a faster rate)
    while (VINPUT_SW = 1)
        //toggle(VLED1)
        if (VLED1 = 1) then
            VLED1 = 0
        else
            VLED1 = 1
        endif                        
        //toggle(VLED2)
        if (VLED2 = 1) then
            VLED2 = 0
        else
            VLED2 = 1
        endif                        
        delayms(100)
    end while
    VLED1 = 1
    VLED2 = 1
    // wait for button release
    while (VINPUT_SW = 0)
    end while
    VLED1 = 0
    VLED2 = 0
end while
    
end program

Post Reply