Go Down

Topic: Port manipulation PINx commands with Arduino Due ? (Read 23309 times) previous topic - next topic

stimmer

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

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

Code: [Select]

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));
}

Due VGA library - http://arduino.cc/forum/index.php/topic,150517.0.html

alvesjc

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
www.aqualedsource.com

westfw

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?

razer93


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

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

Code: [Select]

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 ;)

alvesjc


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

www.aqualedsource.com

seppo

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

testing continues ....

razer93

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

seppo


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

stimmer




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).
Due VGA library - http://arduino.cc/forum/index.php/topic,150517.0.html

seppo

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

alvesjc

#25
Nov 03, 2012, 08:45 pm Last Edit: Nov 03, 2012, 09:04 pm by alvesjc Reason: 1


Code: [Select]

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: [Select]

//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: [Select]

//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));
www.aqualedsource.com

JoeN

#26
Nov 24, 2012, 05:00 am Last Edit: Nov 24, 2012, 08:12 am by JoeN Reason: 1

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

Code: [Select]

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

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.
I have only come here seeking knowledge. Things they would not teach me of in college.

dreschel

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.


dreschel

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?

dishimwe



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: [Select]

    REG_PIOC_ODR = 0x3fc;
    REG_PIOC_PER = 0x3fc;
    int pixelData = REG_PIOC_PDSR >> 2;

Go Up