I was surprised (or simply blissfully ignoring) how much more efficient the Xmega virtual ports are when dealing with single bits...much more code and speed efficient:
This is due to allowing the use of sbi & cbi & in & out
#include <avr/io.h> #define PORTA_Virt VPORT0 // just a naming substitution for clarity #define PORTB_Virt VPORT1 int main(void){ //NOTE the port directions (.DIR) have not been configured, but need to be for actual usage PORTA_Virt.OUT |=PIN4_bm; // set a specific pin using virtual port PORTA.OUTSET=PIN4_bm; // set a pin using std port (same as PORTA_Virt, if already configured as noted below) // this code will compile 4x longer/slower (3x If Z already set)!! PORTB_Virt.OUT &= ~PIN4_bm; // reset a pin using virtual port PORTB.OUTCLR=PIN4_bm; // reset a pin using std port // the following configurations are needed, VPorts are UNASSIGNED upon reset....these must be placed PRIOR to making the above virtual pin changes PORTCFG.VPCTRLA=PORTCFG_VP0MAP_PORTA_gc|PORTCFG_VP1MAP_PORTB_gc; // assign the virtual ports A==>VP0, B==>VP1 PORTCFG.VPCTRLB=PORTCFG_VP2MAP_PORTC_gc|PORTCFG_VP3MAP_PORTD_gc; // assign the virtual ports C==>VP2, D==>VP3 }
The compiled code shows a large improvement with the virtual ports:
PORTA_Virt.OUT |=PIN4_bm; // set a specific pin using virtual port.....NICE AND QUICK 184: 8c 9a sbi 0x11, 4 ; 17 PORTA.OUTSET=PIN4_bm; // set a pin using std port (same as PORTA_Virt, if already configured as noted below) 186: 80 e1 ldi r24, 0x10 ; 16 188: e0 e0 ldi r30, 0x00 ; 0 18a: f6 e0 ldi r31, 0x06 ; 6 18c: 85 83 std Z+5, r24 ; 0x05 .......SING A SAD DOG SONG // this code will compile 4x longer/slower (3x If Z already set)!! PORTB_Virt.OUT &= ~PIN4_bm; // reset a pin using virtual port 18e: ac 98 cbi 0x15, 4 ; 21 PORTB.OUTCLR=PIN4_bm; // reset a pin using std port 190: e0 e2 ldi r30, 0x20 ; 32 192: f6 e0 ldi r31, 0x06 ; 6 194: 86 83 std Z+6, r24 ; 0x06
It would be nice to have some sort of macro to allow "virtual compatibility" (only for a single pin) with a statement such as:
PORTB_Virt.OUTCLR=PIN4_bm; //same as PORTB_Virt.OUT &= ~PIN4_bm;
That shouldn't be impossible, I'll scratch my head on it
Of course, the standard Xmega OUTCLEAR, allows multiple bits to be simultaneously cleared, at about the same rate/length as the mega/tiny read (IN), modify (AND/OR), write (OUT) dance