Port manipulation PINx commands with Arduino Due ?

While trying your sugestion, the errors are now:

D:\Docs\Arduino\arduino-1.5\libraries\UTFT\UTFT.cpp: In constructor 'UTFT::UTFT(byte, int, int, int, int, int)':
D:\Docs\Arduino\arduino-1.5\libraries\UTFT\UTFT.cpp:158: error: invalid types 'const PinDescription [][int*]' for array subscript
D:\Docs\Arduino\arduino-1.5\libraries\UTFT\UTFT.cpp:159: error: invalid types 'const PinDescription [][int*]' for array subscript
D:\Docs\Arduino\arduino-1.5\libraries\UTFT\UTFT.cpp:160: error: invalid types 'const PinDescription [][int*]' for array subscript
D:\Docs\Arduino\arduino-1.5\libraries\UTFT\UTFT.cpp:161: error: invalid types 'const PinDescription [][int*]' for array subscript
D:\Docs\Arduino\arduino-1.5\libraries\UTFT\UTFT.cpp:162: error: invalid types 'const PinDescription [][int*]' for array subscript
D:\Docs\Arduino\arduino-1.5\libraries\UTFT\UTFT.cpp:163: error: invalid types 'const PinDescription [][int*]' for array subscript
D:\Docs\Arduino\arduino-1.5\libraries\UTFT\UTFT.cpp:164: error: invalid types 'const PinDescription [][int*]' for array subscript
D:\Docs\Arduino\arduino-1.5\libraries\UTFT\UTFT.cpp:165: error: invalid types 'const PinDescription [][int*]' for array subscript

chrisbillington:
Hm. I'm not sure what's going on then. If you're just trying to read and write directly from ports, have you tried the method I suggested in reply #3?

Yes, that method solved the compilation problem at least. I can't test it yet because the other errors.

But the port handling is now this:

void UTFT::LCD_Writ_Bus(char VH,char VL, byte mode)
{   
	switch (mode)
	{
(...)
	case 16:
#if defined(__SAM3X8E__)
		//DB00 on PIN37 -> PIO_PC5
		REG_PIOC_ODSR=(VL<<5) & 0x20;
		//DB01 on PIN36 -> PIO_PC4
		REG_PIOC_ODSR=(VL<<3) & 0x10;
		//DB02 on PIN35 -> PIO_PC3
		REG_PIOC_ODSR=(VL<<1) & 0x08;
		//DB03 on PIN34 -> PIO_PC2
		REG_PIOC_ODSR=(VL>>1) & 0x04;
		//DB04 on PIN33 -> PIO_PC1
		REG_PIOC_ODSR=(VL>>3) & 0x02;
		//DB05 on PIN32 -> PIO_PD10
		REG_PIOD_ODSR=(VL<<5) & 0x400;
		//DB06 on PIN31 -> PIO_PA7
		REG_PIOA_ODSR=(VL<<1) & 0x80;
		//DB07 on PIN30 -> PIO_PD9
		REG_PIOD_ODSR=(VL<<2) & 0x200;
		//DB08 on PIN22 -> PIO_PB26
		REG_PIOB_ODSR=(VH<<26) & 0x4000000;
		//DB09 on PIN23 -> PIO_PA14
		REG_PIOA_ODSR=(VH<<13) & 0x4000;
		//DB10 on PIN24 -> PIO_PA15
		REG_PIOA_ODSR=(VH<<13) & 0x8000;
		//DB11 on PIN25 -> PIO_PD0
		REG_PIOD_ODSR=(VH>>3) & 0x01;
		//DB12 on PIN26 -> PIO_PD1
		REG_PIOD_ODSR=(VH>>3) & 0x02;
		//DB13 on PIN27 -> PIO_PD2
		REG_PIOD_ODSR=(VH>>3) & 0x04;
		//DB14 on PIN28 -> PIO_PD3
		REG_PIOD_ODSR=(VH>>3) & 0x08;
		//DB15 on PIN29 -> PIO_PD6
		REG_PIOD_ODSR=(VH>>1) & 0x40;
#endif
		pulse_low(P_WR, B_WR);
		break;
	}
}

void UTFT::_set_direction_registers(byte mode)
{
#if defined(__SAM3X8E__)
	if (mode==16)
	{
		REG_PIOA_OWER=0xc080; //PA7,PA14,PA15 enable
		REG_PIOB_OWER=0x4000000; //PB26 enable
		REG_PIOC_OWER=0x3e; //PC1 - PC5 enable
		REG_PIOD_OWER=0x64f; //PD0-3,PD6,PD9-10 enable
	}
#endif

}

After this, it stoped complaining about the PORT defenitions, so I guess you'r right! :wink:

Hi!

tested the syntax :

int input_data = REG_PIOD_PDSR;

and works ok and the command reads the D port ok with this one command, tested by changing all the input states,

will be testing the A,B and C ports and outputs tomorrow , will report more then,

Chris , thanks for info !

BR,
Seppo

Hi.

Ok, I've figured out what is wrong.

Looking to arduino mega pins_arduino.h we find this:

const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
	// PORTLIST		
	// -------------------------------------------		
	PE	, // PE 0 ** 0 ** USART0_RX	
	PE	, // PE 1 ** 1 ** USART0_TX	
	PE	, // PE 4 ** 2 ** PWM2	
	PE	, // PE 5 ** 3 ** PWM3	
	PG	, // PG 5 ** 4 ** PWM4	
	PE	, // PE 3 ** 5 ** PWM5	
	PH	, // PH 3 ** 6 ** PWM6	
	PH	, // PH 4 ** 7 ** PWM7	
	PH	, // PH 5 ** 8 ** PWM8	
	PH	, // PH 6 ** 9 ** PWM9	
	PB	, // PB 4 ** 10 ** PWM10	
	PB	, // PB 5 ** 11 ** PWM11	
	PB	, // PB 6 ** 12 ** PWM12	
	PB	, // PB 7 ** 13 ** PWM13	
	PJ	, // PJ 1 ** 14 ** USART3_TX	
	PJ	, // PJ 0 ** 15 ** USART3_RX	
	PH	, // PH 1 ** 16 ** USART2_TX	
	PH	, // PH 0 ** 17 ** USART2_RX	
	PD	, // PD 3 ** 18 ** USART1_TX	
	PD	, // PD 2 ** 19 ** USART1_RX	
	PD	, // PD 1 ** 20 ** I2C_SDA	
	PD	, // PD 0 ** 21 ** I2C_SCL	
	PA	, // PA 0 ** 22 ** D22	
	PA	, // PA 1 ** 23 ** D23	
	PA	, // PA 2 ** 24 ** D24	
	PA	, // PA 3 ** 25 ** D25	
	PA	, // PA 4 ** 26 ** D26	
	PA	, // PA 5 ** 27 ** D27	
	PA	, // PA 6 ** 28 ** D28	
	PA	, // PA 7 ** 29 ** D29	
	PC	, // PC 7 ** 30 ** D30	
	PC	, // PC 6 ** 31 ** D31	
	PC	, // PC 5 ** 32 ** D32	
	PC	, // PC 4 ** 33 ** D33	
	PC	, // PC 3 ** 34 ** D34	
	PC	, // PC 2 ** 35 ** D35	
	PC	, // PC 1 ** 36 ** D36	
	PC	, // PC 0 ** 37 ** D37	
	PD	, // PD 7 ** 38 ** D38	
	PG	, // PG 2 ** 39 ** D39	
	PG	, // PG 1 ** 40 ** D40	
	PG	, // PG 0 ** 41 ** D41	
	PL	, // PL 7 ** 42 ** D42	
	PL	, // PL 6 ** 43 ** D43	
	PL	, // PL 5 ** 44 ** D44	
	PL	, // PL 4 ** 45 ** D45	
	PL	, // PL 3 ** 46 ** D46	
	PL	, // PL 2 ** 47 ** D47	
	PL	, // PL 1 ** 48 ** D48	
	PL	, // PL 0 ** 49 ** D49	
	PB	, // PB 3 ** 50 ** SPI_MISO	
	PB	, // PB 2 ** 51 ** SPI_MOSI	
	PB	, // PB 1 ** 52 ** SPI_SCK	
	PB	, // PB 0 ** 53 ** SPI_SS	
	PF	, // PF 0 ** 54 ** A0	
	PF	, // PF 1 ** 55 ** A1	
	PF	, // PF 2 ** 56 ** A2	
	PF	, // PF 3 ** 57 ** A3	
	PF	, // PF 4 ** 58 ** A4	
	PF	, // PF 5 ** 59 ** A5	
	PF	, // PF 6 ** 60 ** A6	
	PF	, // PF 7 ** 61 ** A7	
	PK	, // PK 0 ** 62 ** A8	
	PK	, // PK 1 ** 63 ** A9	
	PK	, // PK 2 ** 64 ** A10	
	PK	, // PK 3 ** 65 ** A11	
	PK	, // PK 4 ** 66 ** A12	
	PK	, // PK 5 ** 67 ** A13	
	PK	, // PK 6 ** 68 ** A14	
	PK	, // PK 7 ** 69 ** A15	
};

const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
	// PIN IN PORT		
	// -------------------------------------------		
	_BV( 0 )	, // PE 0 ** 0 ** USART0_RX	
	_BV( 1 )	, // PE 1 ** 1 ** USART0_TX	
	_BV( 4 )	, // PE 4 ** 2 ** PWM2	
	_BV( 5 )	, // PE 5 ** 3 ** PWM3	
	_BV( 5 )	, // PG 5 ** 4 ** PWM4	
	_BV( 3 )	, // PE 3 ** 5 ** PWM5	
	_BV( 3 )	, // PH 3 ** 6 ** PWM6	
	_BV( 4 )	, // PH 4 ** 7 ** PWM7	
	_BV( 5 )	, // PH 5 ** 8 ** PWM8	
	_BV( 6 )	, // PH 6 ** 9 ** PWM9	
	_BV( 4 )	, // PB 4 ** 10 ** PWM10	
	_BV( 5 )	, // PB 5 ** 11 ** PWM11	
	_BV( 6 )	, // PB 6 ** 12 ** PWM12	
	_BV( 7 )	, // PB 7 ** 13 ** PWM13	
	_BV( 1 )	, // PJ 1 ** 14 ** USART3_TX	
	_BV( 0 )	, // PJ 0 ** 15 ** USART3_RX	
	_BV( 1 )	, // PH 1 ** 16 ** USART2_TX	
	_BV( 0 )	, // PH 0 ** 17 ** USART2_RX	
	_BV( 3 )	, // PD 3 ** 18 ** USART1_TX	
	_BV( 2 )	, // PD 2 ** 19 ** USART1_RX	
	_BV( 1 )	, // PD 1 ** 20 ** I2C_SDA	
	_BV( 0 )	, // PD 0 ** 21 ** I2C_SCL	
	_BV( 0 )	, // PA 0 ** 22 ** D22	
	_BV( 1 )	, // PA 1 ** 23 ** D23	
	_BV( 2 )	, // PA 2 ** 24 ** D24	
	_BV( 3 )	, // PA 3 ** 25 ** D25	
	_BV( 4 )	, // PA 4 ** 26 ** D26	
	_BV( 5 )	, // PA 5 ** 27 ** D27	
	_BV( 6 )	, // PA 6 ** 28 ** D28	
	_BV( 7 )	, // PA 7 ** 29 ** D29	
	_BV( 7 )	, // PC 7 ** 30 ** D30	
	_BV( 6 )	, // PC 6 ** 31 ** D31	
	_BV( 5 )	, // PC 5 ** 32 ** D32	
	_BV( 4 )	, // PC 4 ** 33 ** D33	
	_BV( 3 )	, // PC 3 ** 34 ** D34	
	_BV( 2 )	, // PC 2 ** 35 ** D35	
	_BV( 1 )	, // PC 1 ** 36 ** D36	
	_BV( 0 )	, // PC 0 ** 37 ** D37	
	_BV( 7 )	, // PD 7 ** 38 ** D38	
	_BV( 2 )	, // PG 2 ** 39 ** D39	
	_BV( 1 )	, // PG 1 ** 40 ** D40	
	_BV( 0 )	, // PG 0 ** 41 ** D41	
	_BV( 7 )	, // PL 7 ** 42 ** D42	
	_BV( 6 )	, // PL 6 ** 43 ** D43	
	_BV( 5 )	, // PL 5 ** 44 ** D44	
	_BV( 4 )	, // PL 4 ** 45 ** D45	
	_BV( 3 )	, // PL 3 ** 46 ** D46	
	_BV( 2 )	, // PL 2 ** 47 ** D47	
	_BV( 1 )	, // PL 1 ** 48 ** D48	
	_BV( 0 )	, // PL 0 ** 49 ** D49	
	_BV( 3 )	, // PB 3 ** 50 ** SPI_MISO	
	_BV( 2 )	, // PB 2 ** 51 ** SPI_MOSI	
	_BV( 1 )	, // PB 1 ** 52 ** SPI_SCK	
	_BV( 0 )	, // PB 0 ** 53 ** SPI_SS	
	_BV( 0 )	, // PF 0 ** 54 ** A0	
	_BV( 1 )	, // PF 1 ** 55 ** A1	
	_BV( 2 )	, // PF 2 ** 56 ** A2	
	_BV( 3 )	, // PF 3 ** 57 ** A3	
	_BV( 4 )	, // PF 4 ** 58 ** A4	
	_BV( 5 )	, // PF 5 ** 59 ** A5	
	_BV( 6 )	, // PF 6 ** 60 ** A6	
	_BV( 7 )	, // PF 7 ** 61 ** A7	
	_BV( 0 )	, // PK 0 ** 62 ** A8	
	_BV( 1 )	, // PK 1 ** 63 ** A9	
	_BV( 2 )	, // PK 2 ** 64 ** A10	
	_BV( 3 )	, // PK 3 ** 65 ** A11	
	_BV( 4 )	, // PK 4 ** 66 ** A12	
	_BV( 5 )	, // PK 5 ** 67 ** A13	
	_BV( 6 )	, // PK 6 ** 68 ** A14	
	_BV( 7 )	, // PK 7 ** 69 ** A15	
};

These two arrays are the key to allow to easily choose any pin and immediately know is port and bit number to build a mask.

These arrays are note present in Due pins_arduino.h (that links to variant.cpp).

If I force the pins and get their port and bit, this lib will certainly work, but at the cost of loosing flexibility.

Is there any problem about including this arrays with due pin tables to pins_arduino.h?

I think i've got a little more of this picture.

The compiler complains that:
"
D:\Docs\Arduino\arduino-1.5\libraries\UTFT\UTFT.cpp: In constructor 'UTFT::UTFT(byte, int, int, int, int, int)':
D:\Docs\Arduino\arduino-1.5\libraries\UTFT\UTFT.cpp:158: error: base operand of '->' has non-pointer type 'const PinDescription'
"
When in the UTFT lib the compiler reaches the line 158:

P_RS = portOutputRegister(digitalPinToPort(RS));

Well, this calls from arduino.h the following:

#define digitalPinToPort(P) ( g_APinDescription[P]->pPort )

g_APinDescription[] is one array of type "PinDescription" that is this struct in arduino.h:

/* Types used for the tables below */
typedef struct _PinDescription
{
  Pio* pPort ;
  uint32_t ulPin ;
  uint32_t ulPeripheralId ;
  EPioType ulPinType ;
  uint32_t ulPinConfiguration ;
  uint32_t ulPinAttribute ;
  EAnalogChannel ulAnalogChannel ; /* Analog pin in the Arduino context (label on the board) */
  EAnalogChannel ulADCChannelNumber ; /* ADC Channel number in the SAM device */
  EPWMChannel ulPWMChannel ;
  ETCChannel ulTCChannel ;
} PinDescription ;

This struct is instantiated then with:

/* Pins table to be instanciated into variant.cpp */
extern const PinDescription g_APinDescription[] ;

All this seems logical but it doesn't work.

Based on the info in this link:
http://cplusplus.syntaxerrors.info/index.php?title=Base_operand_of_arrow_has_non-pointer_type_‘Foo’

I've tried to replace this:

#define digitalPinToPort(P) ( g_APinDescription[P]->pPort )

with this:

#define digitalPinToPort(P) ( g_APinDescription[P].pPort )

But then I have the following error:

D:\Docs\Arduino\arduino-1.5\libraries\UTFT\UTFT.cpp: In constructor 'UTFT::UTFT(byte, int, int, int, int, int)':
D:\Docs\Arduino\arduino-1.5\libraries\UTFT\UTFT.cpp:158: error: invalid conversion from 'volatile RwReg' to 'volatile uint8_t*'

RS is pin 38, and that is what is passed to the define.

Can someone help with this? I'm clueless....

I think i've got a little more of this picture.

I can't figure out what you are trying to do, or what you've done. You keep posting segments of pins_arduino.h and variant.cpp, and never the code that you've actually written...

pins_arduino.h and variant.cpp are the modules that translate from the names that the Arduino environment uses (1, 2, 3, PIN_LED_13) to the addresses used by the CPU internally. They have nothing to do with "direct port manipulation" except as way to identify which Arduino pins match up with which ports and bits.

The Arduino pin numbers are small and consecutive integers, while the ports are large 32bit addresses, and the bits are bit numbers. In the Due implementation, the Arduino pin number is used as an index into an array of structures with various information about the pin/port/bit/function. In the MEGA implementation, the pin number is used as an index into various parallel simple arrays that each convey part the same set of information. It's part of the power of the "variant" code setup that two different boards can have substantially different implementations.

And yes, to do direct port manipulation, you give up a LOT of the flexibility that you'd get from using the Arduino pin names.

Hi Westfw.

What I'm trying to do, is to port UTFT library from MEGA to work with DUE. This library is from Henning Karlsen, but since e doesn't have a DUE at the moment, he can't work on the lib now.

The original library is here:

http://www.henningkarlsen.com/electronics/library.php?id=51

What is needed to port is all the low level functions that deal with ports. Part of that is done following reply #3, that is, the TFT data bus. Now I'm stuck in the control pins of the TFT.

You can find attached the library with the changes I've made so far.

My last post shows the point were I'm bumping now.

The code that is failing is in the file "utft.cpp" in the lines mentioned in last post.

Can you or someone else help me out with this?

Thank you.

BR,

Joao

UTFT.zip (706 KB)

The other way of doing direct port manipulation looks like this:

PIOx->register=value;   
long r = PIOx->register;

where x is A,B,C or D and register is as in the data sheet

For example:

PIOB->PIO_SODR=1<<27; //lights the LED
PIOB->PIO_CODR=1<<27; //clears it
boolean p12=!!(PIOD->PIO_PDSR & (1<<8)); //read pin 12

I had a go at writing some digitalReadDirect/digitalWriteDirect functions but you might want to give them some more thorough testing as I only checked if it worked with the LED :slight_smile:

inline void digitalWriteDirect(int pin, boolean val){
  if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

inline int digitalReadDirect(int pin){
  return !!(g_APinDescription[pin].pPort -> PIO_PDSR & g_APinDescription[pin].ulPin);
}

void setup() {                
  pinMode(13, OUTPUT);     
  pinMode(12, INPUT);     
  Serial.begin(9600);
}

void loop() {
  digitalWriteDirect(13, HIGH);   
  delay(1000);           
  digitalWriteDirect(13, LOW);    
  delay(1000);          
  Serial.println(digitalReadDirect(12));
}
1 Like

Hummm, you're using the"."!

g_APinDescription[pin].pPort

but it doesn't work if I put the dot in this line anyway:

#define digitalPinToPort(P) ( g_APinDescription[P]->pPort )

I'll test your code later, maybe I can implement it directly in lib.

Thank you

Now I'm stuck in the control pins of the TFT.

Can't you just use digitalWrite() for the control pins, as a first effort?

stimmer:
The other way of doing direct port manipulation looks like this:

PIOx->register=value;   

long r = PIOx->register;



where x is A,B,C or D and register is as in the data sheet

For example: 


PIOB->PIO_SODR=1<<27; //lights the LED
PIOB->PIO_CODR=1<<27; //clears it
boolean p12=!!(PIOD->PIO_PDSR & (1<<8)); //read pin 12





I had a go at writing some digitalReadDirect/digitalWriteDirect functions but you might want to give them some more thorough testing as I only checked if it worked with the LED :)



inline void digitalWriteDirect(int pin, boolean val){
  if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

inline int digitalReadDirect(int pin){
  return !!(g_APinDescription[pin].pPort -> PIO_PDSR & g_APinDescription[pin].ulPin);
}

void setup() {               
  pinMode(13, OUTPUT);     
  pinMode(12, INPUT);     
  Serial.begin(9600);
}

void loop() {
  digitalWriteDirect(13, HIGH);   
  delay(1000);           
  digitalWriteDirect(13, LOW);   
  delay(1000);         
  Serial.println(digitalReadDirect(12));
}

your code is working pretty well man, thank you a lot... i gained about almost 40% speed in my parallel flash memory writer :wink:

westfw:

Now I'm stuck in the control pins of the TFT.

Can't you just use digitalWrite() for the control pins, as a first effort?

Yes, I'll try that also.

Regards,

Joao

Hello!

tested reading ports A, B and C syncronously and port reading works OK,

but then tried syncronous writing with REG_PIOx_ODSR command did not succeed ,
although bitwise setting with REG_PIOx_SODR and clearing with REG_PIOx_CODR works OK,

I might have something wrong although tried also setting first REG_PIOx_OWER mask bit for those bits I wanted to write
syncronously ,

another test result still: enabled output to several bits with pinmode (xx, OUTPUT) commands but still the REG_PIOx_ODSR does not write
to the PIO port ,

so as a summary so far: input port reading (bytes , words , double words) reading works OK but
output does not work (yet :slight_smile:

testing continues ....

can someone write down the clear way how to manipulate different pins at the same time? i'm quite confused! :S

the reading is easy:

eg.

unsigned long int input_data = REG_PIOC_PDSR;

reads the C -port (32 bit wide) and all the bits simultaneously to input_data variable and fast ,
and I've tested A, B, C and D ports by changing bit states ((work ok with Arduino Due),

but then encountered problems when tried writing in the same way with command eg.

REG_PIOC_ODSR = 0xFF;

which should change all bits 0-15 simultanously to 1, look at my post earlier today, where test results are reported,

BR,
Seppo

seppo:
REG_PIOC_ODSR = 0xFF;

which should change all bits 0-15 simultanously to 1, look at my post earlier today, where test results are reported,

BR,
Seppo

No, that will only set bits 0-7 to 1 (0xFF is 11111111 in binary).

yes , of course 8 bits ,

and it is possible to write simultaneously words and double words (32 bits) but
not all the pins of PIO - ports are connected to Due I/O ,

Seppo

stimmer:

inline void digitalWriteDirect(int pin, boolean val){

if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
 else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

inline int digitalReadDirect(int pin){
 return !!(g_APinDescription[pin].pPort -> PIO_PDSR & g_APinDescription[pin].ulPin);
}

Hi.

Ok, I've managed to put library working with your functions, Thank you!

But it's still very slow running DEMO compared to Chipkit. I know that in chipkit, the entire byte is written to port at once and in due I'm writing bit by bit, but I'm not sure that this is enough for a huge difference in run time for demo. In chipkit it takes around 24s, I'm getting with due 44s.

Is there a way to use ODSR in this functions? Can I write to ODSR bit by bit?

From datasheet, ODSR should be used for synchronous transfer. I'm thinking, maybe using ODSR i might get bet speed.

I was trying to do this without success:

		//DB00 on PIN37 -> PIO_PC5
		REG_PIOC_ODSR=((VL&0x01)<<5) & 0x20;
		//DB01 on PIN36 -> PIO_PC4
		REG_PIOC_ODSR=(VL<<3) & 0x10;
		//DB02 on PIN35 -> PIO_PC3
		REG_PIOC_ODSR=(VL<<1) & 0x08;
		//DB03 on PIN34 -> PIO_PC2
		REG_PIOC_ODSR=(VL>>1) & 0x04;
		//DB04 on PIN33 -> PIO_PC1
		REG_PIOC_ODSR=(VL>>3) & 0x02;
		//DB05 on PIN32 -> PIO_PD10
		REG_PIOD_ODSR=(VL<<5) & 0x400;
		//DB06 on PIN31 -> PIO_PA7
		REG_PIOA_ODSR=(VL<<1) & 0x80;
		//DB07 on PIN30 -> PIO_PD9
		REG_PIOD_ODSR=(VL<<2) & 0x200;
		//DB08 on PIN22 -> PIO_PB26
		REG_PIOB_ODSR=(VH<<26) & 0x4000000;
		//DB09 on PIN23 -> PIO_PA14
		REG_PIOA_ODSR=(VH<<13) & 0x4000;
		//DB10 on PIN24 -> PIO_PA15
		REG_PIOA_ODSR=(VH<<13) & 0x8000;
		//DB11 on PIN25 -> PIO_PD0
		REG_PIOD_ODSR=(VH>>3) & 0x01;
		//DB12 on PIN26 -> PIO_PD1
		REG_PIOD_ODSR=(VH>>3) & 0x02;
		//DB13 on PIN27 -> PIO_PD2
		REG_PIOD_ODSR=(VH>>3) & 0x04;
		//DB14 on PIN28 -> PIO_PD3
		REG_PIOD_ODSR=(VH>>3) & 0x08;
		//DB15 on PIN29 -> PIO_PD6
		REG_PIOD_ODSR=(VH>>1) & 0x40;

The working code is:

		//DB00 on PIN37 -> PIO_PC5
		digitalWriteDirect(37,(VL & 0x01));
		//DB01 on PIN36 -> PIO_PC4
		digitalWriteDirect(36,(VL & 0x02));
		//DB02 on PIN35 -> PIO_PC3
		digitalWriteDirect(35,(VL & 0x04));
		//DB03 on PIN34 -> PIO_PC2
		digitalWriteDirect(34,(VL & 0x08));
		//DB04 on PIN33 -> PIO_PC1
		digitalWriteDirect(33,(VL & 0x10));
		//DB05 on PIN32 -> PIO_PD10
		digitalWriteDirect(32,(VL & 0x20));
		//DB06 on PIN31 -> PIO_PA7
		digitalWriteDirect(31,(VL & 0x40));
		//DB07 on PIN30 -> PIO_PD9
		digitalWriteDirect(30,(VL & 0x80));
		//DB08 on PIN22 -> PIO_PB26
		digitalWriteDirect(22,(VH & 0x01));
		//DB09 on PIN23 -> PIO_PA14
		digitalWriteDirect(23,(VH & 0x02));
		//DB10 on PIN24 -> PIO_PA15
		digitalWriteDirect(24,(VH & 0x04));
		//DB11 on PIN25 -> PIO_PD0
		digitalWriteDirect(25,(VH & 0x08));
		//DB12 on PIN26 -> PIO_PD1
		digitalWriteDirect(26,(VH & 0x10));
		//DB13 on PIN27 -> PIO_PD2
		digitalWriteDirect(27,(VH & 0x20));
		//DB14 on PIN28 -> PIO_PD3
		digitalWriteDirect(28,(VH & 0x40));
		//DB15 on PIN29 -> PIO_PD6
		digitalWriteDirect(29,(VH & 0x80));

stimmer:
I had a go at writing some digitalReadDirect/digitalWriteDirect functions but you might want to give them some more thorough testing as I only checked if it worked with the LED :slight_smile:

inline void digitalWriteDirect(int pin, boolean val){

if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
 else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

inline int digitalReadDirect(int pin){
 return !!(g_APinDescription[pin].pPort -> PIO_PDSR & g_APinDescription[pin].ulPin);
}

They seem to work fine. I just used it for my first sketch for my Due, a comparison of port switching and square wave generation using DigitalWrite vs. direct writing using your inline function. Big difference, this is what it looks like on my scope (it overshoots the square because I have a long lead which I corrected for the second measurement):

The waves are a whole lot squarer when running at 1% of the maximum speed. :slight_smile:

Sorry for the bad smartphone pics, I haven't figured out how to properly screen capture on the scope yet and I can't open the manual right now because Adobe Acrobat is having a weird fit.

To use REG_PIOD_ODSR use must first enable the bits with REG_PIOD_OWER (the output write enable).
For instance:

void setup() {
pinMode(12, OUTPUT);
pinMode(14, OUTPUT);
pinMode(15, OUTPUT);
REG_PIOD_OWER = 0xFFFF;
}

void loop() {
REG_PIOD_ODSR = 0x0130;
REG_PIOD_ODSR = 0x0000;
REG_PIOD_ODSR = 0x0130;
}

Will produce a ~23ns low going pulse on pin 12, 14 and 15. For some reason you need to set the pinModes to make this work.