Arduino Forum

Products => Arduino Due => Topic started by: seppo on Oct 30, 2012, 12:27 pm

Title: Port manipulation PINx commands with Arduino Due ?
Post by: seppo on Oct 30, 2012, 12:27 pm
Hello!

are the port manipulation commands supported in Due ? I have used PINx  commands with Arduino Mega to read and write bytes instead of digitalRead() and -Write() ,
and would like to do the same with Due ,
and if byte (or word size 16 bits) simultaneous reading and writing is possible , how should the PIN command syntax be ?

BR,

Seppo 
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: chrisbillington on Oct 31, 2012, 01:05 pm
I'm trying to work this out as well, at the moment I'm looking in arduino-1.5/hardware/arduino/sam/variants/arduino_due_x/variants.cpp and variants.h, but I haven't figured it out yet.
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: baltasar on Oct 31, 2012, 01:58 pm
Read here there some more info (all the way to the end): http://arduino.cc/forum/index.php/topic,129407.0.html

I'm also trying to do port manipulation.
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: chrisbillington on Oct 31, 2012, 02:23 pm
It looks like you might be able to do:
   
Code: [Select]
REG_PIOx_ODSR = data_to_set;

to set output data, and:
   
Code: [Select]
input_data = REG_PIOx_PDSR;

to get input data, where x is A,B,C or D. The acronyms are "output data status register" and "pin data status register". You may first need to enable output by writing ones to PIOx_OWER (output write enable register). If you've already used standard arduino calls to set the pin in question to be an output, I think that's all you'll need to do. See page 646 of the datasheet for more info:

http://www.atmel.com/Images/doc11057.pdf

The registers all follow the same naming convention, it's always REG_PIOx_<whatever>, so it's easy to translate register names in the datasheet to variable names in your sketch.

I can't test as I don't have a Due yet, I'd love to know if this works though.
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: alvesjc on Nov 01, 2012, 01:27 am
Hi.

Like Baltasar, I'm struggling with this issue also.

The compiler likes that method to deal with ports, but now I'm stuck after. It has something to do with pins_arduino.h.

When compiler gets this lines:

P_RS   = portOutputRegister(digitalPinToPort(RS));
B_RS   = digitalPinToBitMask(RS);
P_WR   = portOutputRegister(digitalPinToPort(WR));
B_WR   = digitalPinToBitMask(WR);
P_CS   = portOutputRegister(digitalPinToPort(CS));
B_CS   = digitalPinToBitMask(CS);
P_RST   = portOutputRegister(digitalPinToPort(RST));
B_RST   = digitalPinToBitMask(RST);

It says:

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'
D:\Docs\Arduino\arduino-1.5\libraries\UTFT\UTFT.cpp:159: error: base operand of '->' has non-pointer type 'const PinDescription'
D:\Docs\Arduino\arduino-1.5\libraries\UTFT\UTFT.cpp:160: error: base operand of '->' has non-pointer type 'const PinDescription'
D:\Docs\Arduino\arduino-1.5\libraries\UTFT\UTFT.cpp:161: error: base operand of '->' has non-pointer type 'const PinDescription'
D:\Docs\Arduino\arduino-1.5\libraries\UTFT\UTFT.cpp:162: error: base operand of '->' has non-pointer type 'const PinDescription'
D:\Docs\Arduino\arduino-1.5\libraries\UTFT\UTFT.cpp:163: error: base operand of '->' has non-pointer type 'const PinDescription'
D:\Docs\Arduino\arduino-1.5\libraries\UTFT\UTFT.cpp:164: error: base operand of '->' has non-pointer type 'const PinDescription'
D:\Docs\Arduino\arduino-1.5\libraries\UTFT\UTFT.cpp:165: error: base operand of '->' has non-pointer type 'const PinDescription'

This is pointing to file variant.cpp, to this function:

/*
* Pins descriptions
*/
extern const PinDescription g_APinDescription[]=
{
  // 0 .. 53 - Digital pins
  // ----------------------
(...)

The operand '->' is not seen inside the function, I don't understand what the compiler want.

Can someone help?
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: chrisbillington on Nov 01, 2012, 01:38 am
alvesjc,

I'm not sure what you're doing, but it looks like the functions you're calling expect pointers to PinDescriptions objects, and that you're giving them actual PinDescription objects rather than pointers. So the -> operator (which may be implicit in that function even though you can't see it) fails. See here for an explanation:

http://stackoverflow.com/questions/1238613/what-is-the-difference-between-the-dot-operator-and-in-c

So I can't tell from your code which variables are PinDescriptions, but if you put an ampersand in front of them, you'll be converting them to pointers and then the -> operator will work.

So if RS is a PinDescription, try digitalPinToPort(&RS).
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: alvesjc on Nov 01, 2012, 01:52 am
Hi.

RS is a variable, basically, the pin corresponding to RS signal to TFT. RS is for example, PIN39, is passed when the lib is initialized:

"
class UTFT
{
   public:
      UTFT();
      UTFT(byte model, int RS, int WR,int CS, int RST, int SER=0);
(...)
"
RS is for exemple, 39.

Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: chrisbillington on Nov 01, 2012, 01:55 am
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?
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: alvesjc on Nov 01, 2012, 01:55 am
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
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: alvesjc on Nov 01, 2012, 01:59 am

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:

Code: [Select]

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! ;)
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: seppo on Nov 01, 2012, 07:45 pm
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
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: alvesjc on Nov 01, 2012, 11:44 pm
Hi.

Ok, I've figured out what is wrong.

Looking to arduino mega pins_arduino.h we find this:

Code: [Select]
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?
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: alvesjc on Nov 02, 2012, 02:35 am
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:

Code: [Select]

/* 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_%E2%80%98Foo%E2%80%99 (http://cplusplus.syntaxerrors.info/index.php?title=Base_operand_of_arrow_has_non-pointer_type_%E2%80%98Foo%E2%80%99)

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....
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: westfw on Nov 02, 2012, 04:22 am
Quote
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.
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: alvesjc on Nov 02, 2012, 08:50 am
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 (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
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: stimmer on Nov 02, 2012, 12:55 pm
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));
}

Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: alvesjc on Nov 02, 2012, 01:27 pm
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
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: westfw on Nov 02, 2012, 06:32 pm
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?
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: razer93 on Nov 02, 2012, 08:10 pm

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 ;)
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: alvesjc on Nov 02, 2012, 08:24 pm

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

Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: seppo on Nov 02, 2012, 09:11 pm
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 ....
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: razer93 on Nov 02, 2012, 09:22 pm
can someone write down the clear way how to manipulate different pins at the same time? i'm quite confused! :S
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: seppo on Nov 02, 2012, 09:42 pm

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
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: stimmer on Nov 02, 2012, 09:45 pm



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).
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: seppo on Nov 03, 2012, 09:55 am
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
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: alvesjc on Nov 03, 2012, 08:45 pm


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));
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: JoeN on Nov 24, 2012, 05:00 am

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

(http://arduino.cc/forum/index.php?action=dlattach;topic=129868.0;attach=30010)

(http://arduino.cc/forum/index.php?action=dlattach;topic=133923.0;attach=30020)

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.
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: dreschel on Jan 01, 2013, 01:27 am
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.

Title: DAC Speed
Post by: dreschel on Jan 01, 2013, 02:10 am
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?
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: dishimwe on Apr 16, 2013, 03:10 am


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;
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: blazek on May 19, 2013, 09:22 pm
Hi guys,
I would like to ask if is possible to generate square waves with digitalWriteDirect?
this code
Code: [Select]
void loop() {
 digitalWriteDirect(9, HIGH);          
 digitalWriteDirect(9, LOW);        
}

produces these waves (sry for bad quality)
http://imageshack.us/f/838/19052013i.jpg/ (http://imageshack.us/f/838/19052013i.jpg/)
thanks
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: stimmer on May 19, 2013, 11:56 pm
The squarewave is uneven because of function call overhead. You can lessen this by making your own loop:

Code: [Select]
void loop() {
  for(;;){
    digitalWriteDirect(9, HIGH);           
    digitalWriteDirect(9, LOW);         
  }
}
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: JoeN on May 20, 2013, 07:13 am
Code: [Select]
void loop() {
  for(;;){
    digitalWriteDirect(9, HIGH);           
    digitalWriteDirect(9, LOW);   
    digitalWriteDirect(9, HIGH);           
    digitalWriteDirect(9, LOW);   
    digitalWriteDirect(9, HIGH);           
    digitalWriteDirect(9, LOW);   
... repeat many times      
  }
}


Even with the tighter loop the square wave will be uneven because of the looping overhead of 3 or 4 machine cycles.  You can cheat by repeating that block of code a bunch of times (feel free to hold ctrl-v down and paste it in a few hundred times).  The more there is before the eventual hiccup, the better chance your scope will have at stabilizing the wave.
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: blazek on May 20, 2013, 10:58 pm
thanks a lot =) now I have nice sinus wave about 20MHz =)
and one more question:
I want to make frequency generator with this utility so is there any documentation about counting ticks? because with msDelay I can do freq. about several thousand KHz (not enough for me =/)..
thanks
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: MsClaude on May 29, 2013, 02:23 pm
Quote
I want to make frequency generator with this utility so is there any documentation about counting ticks?


=> Timer Counter (TC)!
You can count the clocks of MCK/2 (=42MHz)

Quote
ATMELSAM(datasheet) 37.1 Description
The Timer Counter (TC) includes three identical 32-bit Timer Counter channels.


Start the counter, read the counter (Counter Value register)  or generate an interrupt (Interrupt Enable Register) and react
to your choosen number of counts.

Sound easy, but its a it lot of register manipulation. Maybe  you can find a lib for he TC?
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: blazek on Jun 01, 2013, 01:54 pm
Could you be a bit more concrete please? I with code above I have got 32Mhz max... At the moment I think there is no working counter for Due, or am I wrong?
thanks
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: MsClaude on Jun 12, 2013, 01:09 am
Sorry, haven't been here for some time.
I dunno understand what exactly you want, so here just a short example of running Timer counter TC0
at 42 MHz. Maybe this is something that can fit your needs.
Sketch starts and reads (CV = counter value) counter.

Code: [Select]

void setup(){  Serial.begin(9600); }

void loop()
{
unsigned long v[10];
int i;
  PMC->PMC_PCER0 = 1<<27;  // PMC: Enable Timer TC0
  TC0->TC_CHANNEL[0].TC_CMR = 0;  // Control mode reg.: set Clock to MCK/2 = 42 MHz 
  TC0->TC_CHANNEL[0].TC_CCR = 4 + 1;  // activate Timer:  // Start + Enable
  Serial.println("---------------------------------------------------------");
  Serial.println("-------       delay is not exackt, TC0 is!      ---------");
  Serial.println("---------------------------------------------------------");
  Serial.println("Delayed Readout (24 us -> ~1000 Ticks)");
  TC0->TC_BCR = 1;  // restart(sync)
  for(i=0; i<10; i++) { v[i]= TC0->TC_CHANNEL[0].TC_CV;  delayMicroseconds(24); }
  for(i=0; i<10; i++) { Serial.print(i); Serial.print(": "); Serial.println(v[i]); }
  delay(5000); 
  Serial.println("---------------------------------------------------------");
  Serial.println("Endless Readout (1s -> +42 000 000)");
  TC0->TC_BCR = 1;  // restart(sync)
  while(1==1)  { Serial.println(TC0->TC_CHANNEL[0].TC_CV); delay(1000); }
}
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: iz4afl on Jul 18, 2013, 02:47 pm

The squarewave is uneven because of function call overhead. You can lessen this by making your own loop:

Code: [Select]
void loop() {
  for(;;){
    digitalWriteDirect(9, HIGH);           
    digitalWriteDirect(9, LOW);         
  }
}




To make HIGH and LOW phases simmetric, just add a cuple of NOP (No Operation) after the digitalWriteDirect(9, HIGH) :

Code: [Select]

#define NOP __asm__ __volatile__ ("nop\n\t");

...

void loop() {
  for(;;){
    digitalWriteDirect(9, HIGH);
    NOP
    ...
    NOP   
    digitalWriteDirect(9, LOW);         
  }
}


Each NOP extends the HIGH phase by  1 clock cycle, i.e. 12 ns on DUE (1/84 MHz).
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: Professor_Oak on Jun 11, 2014, 12:48 am
I know that this is an old thread but I found the answer and thought I'd share.

You can find the register info for each pin on the Arduino website at:
http://arduino.cc/en/Hacking/PinMappingSAM3X (http://arduino.cc/en/Hacking/PinMappingSAM3X)

The registers are listed in the file instance_piob.h. These registers are 32 bit since the Due uses 32 bit architecture. Instead of setting a register to 1 and 0 for High and Low, there is a set register (SODR) and a clear register (CODR).

Code: [Select]

// Enable
REG_PIO[port]_SODR = [Pin mask];
// Disable
REG_PIO[port]_CODR = [Pin mask];


For example to blink pin 13 you could use the following code. From the link provided, the SAM3X pin name of 13 is PB27 so the port is B and the bit is 27
Code: [Select]

REG_PIOB_SODR = 0x1 << 27;
delay(1000);
REG_PIOB_CODR = 0x1 << 27;
delay(1000);


Using this method you could set multiple pin simultaneously, etc. There is a simpler way to do this if you do not know the port information because it is stored in the array g_APinDescription for each pin so you could save the reg address in a local variable or just access the array.

Code: [Select]

g_APinDescription[13].pPort->PIO_SODR = g_APinDescription[13].ulPin; // ulPin is the mask for that one pin so 1 << 27


Speedwise, I did a comparison and the results were 166us vs 5148us which is just over 31 times faster.

Code: [Select]

time = millis();
  for (int i = 0; i < 1000000; i++) {
    REG_PIOB_SODR = mask;
    REG_PIOB_CODR = mask;
  }
  Serial.println(millis() - time);
 
  time = millis();
  for (int i = 0; i < 1000000; i++) {
    digitalWrite(13, 1);
    digitalWrite(13, 0);
  }
  Serial.println(millis() - time);
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: Measureino on Jun 16, 2014, 05:35 pm
Code: [Select]

REG_PIOB_SODR = 0x1 << 27;
delay(1000);
REG_PIOB_CODR = 0x1 << 27;
delay(1000);

Although not having deep knowledges I could follow this.

But I don't know how to use this to
a) convert data on 8 input pins to a one byte  value and
b) set other 8 output pins to the value of another byte value
both as quick as possible.
There are no limitations which pins to use as long as I can use Serial Input.

Can you help me?

Thanks!
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: iana on Jan 28, 2015, 11:07 pm
Code: [Select]

REG_PIOB_SODR = 0x1 << 27;
delay(1000);
REG_PIOB_CODR = 0x1 << 27;
delay(1000);

Although not having deep knowledges I could follow this.

But I don't know how to use this to
a) convert data on 8 input pins to a one byte  value and
b) set other 8 output pins to the value of another byte value
both as quick as possible.
There are no limitations which pins to use as long as I can use Serial Input.

Can you help me?

Thanks!
Hi, i know this is an old thread, but i still haven't found an easy way to put this together. i'm using an Arduino Mega 1280, with portA and PORTC and it's working ok.

Now i need to take this to Arduino Due, and i couldnt find a way to do it the same way.

coul you explain it again like for very dummies?




Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: AlfaOmega on Feb 24, 2015, 03:05 am

Thank you very much Professor_Oak!


iana - in order for this code to work you have to set the pin as output,  just like in the Blink example.
_
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: iana on Mar 19, 2015, 04:56 pm
Ok, the problem is that due layout dose not have the same ports as Arduino UNO or Mega, so there is no way to manipulate them like PORTC or PORTA, there is a way to do the same, but it's a really bad headache to find out how.

Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: Palliser on Mar 19, 2015, 11:17 pm
Hello iana,

To manipulate individual pins in Arduino Due you have to use Graynomad pinout diagram...

http://forum.arduino.cc/index.php?topic=132130.0 (http://forum.arduino.cc/index.php?topic=132130.0)

...with the following code lines:

Code: [Select]
// Pin HIGH
REG_PIO[port]_SODR = 0x1 << [port Pin];

// Pin LOW
REG_PIO[port]_CODR = 0x1 << [port Pin];


For example, if you want to set HIGH pin 13, look at its port pin (clear yellow background) which is B.27. This indicates pin 27 of port B. Thus,

Code: [Select]
REG_PIOB_SODR = 0x1 << 27;

if you want to set LOW pin 36, its port pin is C.4. Thus,

Code: [Select]
REG_PIOC_CODR = 0x1 << 4;

if you want to set LOW pin A7, its port pin is A.2. Thus,

Code: [Select]
REG_PIOA_CODR = 0x1 << 2;

and so on....

p

Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: jowen on Mar 22, 2015, 03:45 am
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));
}


I am currently trying to run the command digitalReadDirect() in my program.

Each iteration in the loop, the command is run to see if there is a LOW or HIGH state, and a variable is set to that state. In other words, I'm trying to synchronize a certain operation with an input square wave, changing from 0V to 3V. After the program changes the state of a variable 'volatile int state' to HIGH or LOW, I have an if(state == LOW) statement to determine whether an operation should run at that time.

The if(LOW) statement seems to operate correctly asynchronously to the square wave, so I had high hopes. The operation ran when the square wave was LOW, and stopped when the square wave was HIGH.

When I attempted the if(HIGH) statement, the operation was never triggered, and the signal remained LOW regardless of the square wave input.

Can anyone explain why the if(HIGH) statement might not correctly trigger the operation ?

I was using digital pin 12 as a square wave input, and I am trying to trigger an operation output on DAC0. I am using this command because I need my output to trigger quickly, and it did work asynchronously.

I think that was clear enough, but ask questions if needed, I will check up on this.
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: iana on Mar 22, 2015, 09:18 pm
Hello, again.
Did any of you know how to start the clock that makes input mode posible in arduino DUE.

I'm doing direct port manipulation, but to be able to read direct from a pin, i'm currently using

pinMode(pin,input), where pin, is a non used pin of the port.

acording to the SAMx documentation, you do need to start this clock for each port. but i couldn't find how to do this, any other way
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: MorganS on Mar 23, 2015, 05:48 am
Why do you not use pinMode(pin, INPUT) for the pins you are actually using? That will set up the port in the correct way.
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: c0rnmuffin on Apr 09, 2015, 12:02 am
Hi everyone,
I've been reading lots of forum posts on Due port manipulation and am just looking for some clarification now.  Can somebody confirm that we don't need to worry about overwriting another pin when we set or clear with SODR and CODR?  So there is no need to use bitwise operators to make sure the other pins in the register are preserved?

Also, since these are registers, I would think it's the value in the register that matters.  But, for example, in this code:
Code: [Select]
PIOB->PIO_SODR=1<<27; //lights the LED
PIOB->PIO_CODR=1<<27; //clears it

Now the bit at 1<<27 is set for both SODR and CODR.  So is it the actual setting of the register that sets or clears the pin output, not the value in there itself?  And then if I want to pull the value of an output pin from looking at its register (the way you could, say, by looking at PORTD with other Arduinos), I would look at PDSR?

Thanks!
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: c0rnmuffin on Apr 13, 2015, 04:15 pm
In case anyone is interested, I wrote a quick sketch to test this out.  SODR and CODR seem to always be 0, even after they're "set" to 1 to set or clear a pin.  But the pin value does change as read from PDSR.

Another thing I noticed though is that I can only get pin values from PDSR (for output pins- I didn't try input pins)- from PORTC.  PORTA, PORTB and PORTD always return 0.  I can just use PORTC pins, but if anyone knows what's going on...
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: sayrol on Jul 05, 2015, 12:51 pm
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));
}


Hi,im new in this forum, but i'd like to know where do you get this function (g_APinDescription[pin].pPort) from. Because i was looking for in datasheet ATMEL-SAM3X and i haven't found anything. Thanks
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: NirajPrakashKini on Nov 05, 2015, 12:46 pm
//Try this out. It works.

void setup()
{
  REG_PIOB_OWER = 0xFFFFFFFF;     // Enable PORT B
  REG_PIOB_OER =  0xFFFFFFFF;     // Set PORT B as output port
}

void loop()
{   
   REG_PIOB_ODSR = 0xFFFFFFFF;   //set all pins of PORT B
   delay(100);
   REG_PIOB_ODSR = 0x00000000;  //clear all pins of port B
   delay(100);
}
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: westfw on Nov 06, 2015, 07:51 am
To "cache" the port info and bitmask for a "fast SPI" function (as was implied in some of the early messages in the thread), you could use code like:

Code: [Select]
  Pio *p = digitalPinToPort(13);
  uint32_t b = digitalPinToBitMask(13);
  while (1) {
    p->PIO_SODR = b;
    p->PIO_CODR = b;
  }


That yields a crappy-looking waveform of about 16MHz on my scope, and produces code like:
Code: [Select]

   80152:       4a04            ldr     r2, [pc, #16]   ;get pin desc array
   80154:       f8d2 316c       ldr.w   r3, [r2, #364]  ; get pio ptr
   80158:       f8d2 2170       ldr.w   r2, [r2, #368]  ; get bitmask
   8015c:       631a            str     r2, [r3, #48]   ; set
   8015e:       635a            str     r2, [r3, #52]   ; clear
   80160:       e7fc            b.n     8015c <setup+0x14> ; loop


Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: castfxman on Feb 03, 2016, 06:34 pm
This looks like the section I'm looking for, if I wanted to use the PC20 pin which is not in the variant.h or variant.cpp files, how does it get called out in the sketch?  It seems as if the h and .cpp files won't need rewriting if PIOC-PC20 can somehow be declared by using pinMode() or digitalWrite() in the setup and loop.  The examples I've seen of PC20 being utilized by Digistump and Taijiuno both write different versions of the variant.h and variant.cpp files but this should not be required for just one pin correct?
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: westfw on Feb 03, 2016, 06:42 pm
The only way to have a pin available for digitalWrite() and similar arduino functions is to have it defined in the variant files, even if it is "just one pin."   You CAN write to/from it with the direct IO calls being discussed here, regardless of whether it's available to the arduino functions:
Code: [Select]
PIOC->PIO_SODR=1<<20; //Set C20
PIOC->PIO_CODR=1<<20; //clears it



(you'd probably need something similar to do pinMode())
Title: Re: Port manipulation PINx commands with Arduino Due ?
Post by: castfxman on Feb 03, 2016, 07:41 pm
Thank you very much for these function.  So if I want the pin set I probably don't need the line that clears it, is this correct?  I am currently not using pin 33 or PC1, so I changed PC1 to PC20 in the variant.cpp file so now it should have a definition.  Because I don't think I can give it a pin number unless I tack it on the end and call it pin 92.  But replacing it with PC1 hopefully will work easier.  Does it matter where I put these?  Such as before the void setup or in the void loop, everything verifies no matter where it is so it seems they work the same everywhere/