Pages: 1 [2] 3   Go Down
Author Topic: Port manipulation PINx commands with Arduino Due ?  (Read 15321 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
God Member
*****
Karma: 32
Posts: 506
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The other way of doing direct port manipulation looks like this:
Code:
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:
Code:
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   smiley

Code:
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));
}
Logged


0
Offline Offline
Jr. Member
**
Karma: 1
Posts: 84
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged


SF Bay Area (USA)
Offline Offline
Tesla Member
***
Karma: 106
Posts: 6373
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The other way of doing direct port manipulation looks like this:
Code:
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:
Code:
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   smiley

Code:
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 smiley-wink
Logged

0
Offline Offline
Jr. Member
**
Karma: 1
Posts: 84
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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

Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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  smiley

testing continues ....
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


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
Logged

Offline Offline
God Member
*****
Karma: 32
Posts: 506
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset



 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).
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

0
Offline Offline
Jr. Member
**
Karma: 1
Posts: 84
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


Code:
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:

Code:
//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:

Code:
//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));
« Last Edit: November 03, 2012, 03:04:18 pm by alvesjc » Logged


More Cowbell
Offline Offline
Edison Member
*
Karma: 11
Posts: 1025
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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   smiley

Code:
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. smiley

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.


* ArduinoDueSqureWave.png (926.12 KB, 984x696 - viewed 634 times.)
« Last Edit: November 24, 2012, 02:12:14 am by JoeN » Logged

Vexatious Sampler

0
Offline Offline
Newbie
*
Karma: 1
Posts: 10
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Logged

0
Offline Offline
Newbie
*
Karma: 1
Posts: 10
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't know if any one has posted on this yet, fastest update rate for a DAC(?). Here is some code:

int j = 0, topcount = 5;

void setup() {               
  // this is a cheat - enable the DAC
  analogWrite(DAC0,0);
}

void loop() {
 // write directly 
  dacc_write_conversion_data(DACC_INTERFACE, 0x0000);
  for (j = 0;j < topcount;j++);
//  delayMicroseconds(1);
  dacc_write_conversion_data(DACC_INTERFACE, 0x0400);
  for (j = 0;j < topcount;j++);
//  delayMicroseconds(1);
  dacc_write_conversion_data(DACC_INTERFACE, 0x0800);
  for (j = 0;j < topcount;j++);
//  delayMicroseconds(1);
  dacc_write_conversion_data(DACC_INTERFACE, 0x0C00);
  for (j = 0;j < topcount;j++);
//  delayMicroseconds(1);
  dacc_write_conversion_data(DACC_INTERFACE, 0x0FFF);
  for (j = 0;j < topcount;j++);
//  delayMicroseconds(1);
  dacc_write_conversion_data(DACC_INTERFACE, 0x0C00);
  for (j = 0;j < topcount;j++);
//  delayMicroseconds(1);
  dacc_write_conversion_data(DACC_INTERFACE, 0x0800);
  for (j = 0;j < topcount;j++);
//  delayMicroseconds(1);
  dacc_write_conversion_data(DACC_INTERFACE, 0x0400);
  for (j = 0;j < topcount;j++);
//  delayMicroseconds(1);
  dacc_write_conversion_data(DACC_INTERFACE, 0x0000);
  for (j = 0;j < topcount;j++);

}

This code produces a triangular four steps up, four steps down ramp that goes from about 480mV to 2.32V. Each step is about 680ns wide.
The waveform becomes unstable below topcount = 5. Is this the fastest DAC step rate?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


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

How did you read port C? I tried this but it does not work:
Code:
    REG_PIOC_ODR = 0x3fc;
    REG_PIOC_PER = 0x3fc;
    int pixelData = REG_PIOC_PDSR >> 2;
Logged

Pages: 1 [2] 3   Go Up
Jump to: